【问题标题】:How to access getter/setter accessors from angular 4 in template binding?如何在模板绑定中从 Angular 4 访问 getter/setter 访问器?
【发布时间】:2017-08-12 09:33:16
【问题描述】:

假设我有以下 getter/setter 方法

get next() {
  console.log(this.people[this._index], this._index);
  return this.people[this._index];
}

set next(i: any) {
  this._index = (+i) + 1;
  this._index = (+i) % this.people.length;
}

我想通过以下方式调用它:

<ng-template ngFor let-person="$implicit" [ngForOf]="people" let-i=index let-last=last>
  <app-card [cardItem]="people[i]" [nextCard]="next(i)"></app-card>
</ng-template>

PS:把它想象成圆形数组。在哪里我需要上一个、当前和下一个项目。

但是我得到以下错误

Angular:成员“下一个”不可调用

这是为什么呢?解决办法是什么?

谢谢

编辑

感谢大家的帮助和解释。在您的帮助下,我设法使它工作:

&lt;app-card [currentCard]="people[i]" [nextCard]="people[i === people.length - 1 ? 0: i + 1]" [prevCard]="i == 0 ? people[people.length - 1] : people[i - 1]"&gt;&lt;/app-card&gt;

所以它几乎是圆形数组。 假设我们有以下内容:

people["James Dan", "Aluan Haddad", "Jota Toledo"]

条件很少:

  1. 如果我站在数组的开头(即index = 0) - 那么我的prev 将是people[people.length - 1],这是数组中的最后一个元素。如果我的当前在索引 1 上,那么我的上一个将是索引 0,下一个将是索引 2。

【问题讨论】:

  • 我在回答中又添加了一个示例。这显示了您将如何正确使用属性,并演示如何构建显示结构,同时避免模板的复杂性。

标签: angular typescript getter-setter templatebinding


【解决方案1】:

一般来说,Angular 模板语法是 JavaScript 语法的一个子集,有一些显着差异和许多限制。

但是,您在此处拥有的内容实际上在 JavaScript 中也是无效的。调用属性访问器是无效的。永远。

给定以下属性

get p() {
  console.info('read p');
  return this.wrapped;
}
set p(value) {
  console.info('wrote p');
  this.wrapped = value;
}

get 访问器在读取如此命名的属性时被隐式调用。

例如:

console.log(o.p); // read p

当如此命名的属性被写入时,set 访问器被隐式调用。

例如:

o.p = x; // wrote p;

同样的规则也适用于 Angular 模板。

但是,你的例子

<app-card [cardItem]="people[i]" [nextCard]="next(i)">

表明这里的属性不是您想要的。

属性的正确用法意味着以下语法

<app-card [cardItem]="people[i]" [nextCard]="next = i">

我不相信 Angular 模板语法支持它,即使它没有多大意义并且难以阅读。

相反,您应该创建一个返回值的方法

getNext(i: number) {
  this._index = i + 1;
  this._index = i % this.people.length;
  return this.people[this._index];
}

然后在你的模板中用作

<app-card [cardItem]="people[i]" [nextCard]="getNext(i)">

话虽如此,我认为整个设计是有问题的。您似乎正在通过扭曲来独立于自然维护它的数组来存储多余的可变状态。

我相信完全删除方法和属性并使用会更好地为您服务

<app-card
  *ngFor="let person of people; let i = index"
  [previousCard]="people[i === 0 ? people.length - 1 : i - 1]" 
  [cardItem]="person"
  [nextCard]="people[i === people.length - 1 ? 0 : i + 1]">

如果您想要更简洁的语法,您可以定义一个属性,仅使用 get 访问器,将您的数组视图作为具有 previouscurrentnext 属性的对象返回。

get peopleAsPreviousCurrentAndNextTriplets() {
  return this.people.map((person, i) => ({
    previous: this.people[i === 0 ? this.people.length - 1 : i - 1],
    current: person,
    next: this.people[i === this.people.length - 1 ? 0 : i + 1]
  }));
}

这在复杂代码中更具可读性,因为它抽象出索引以获得更多我们可以直接使用的语义属性。也许更重要的是,它使 TypeScript 的世界级工具能够验证计算。

<app-card
  *ngFor="let item of peopleAsPreviousCurrentAndNextTriplets"
  [previousCard]="item.previous" 
  [cardItem]="item.current"
  [nextCard]="item.next">

我们就这样绕了一圈。请注意我们如何定义 get 访问器,以及我们如何在没有 () 的情况下读取它定义的属性,隐式调用该访问器。

对于这种情况,最后一个示例可能有点矫枉过正,但我​​认为它仍然很有用。

【讨论】:

  • 使用 getNext 方法的方法是必要的,因为 op 显然希望为索引 array.length 处的项目获取索引 0 处的项目
  • 对不起,表达方式有误。我的意思是你刚才说的:D
  • 大声笑,很抱歉,没有太注意你的回答。感谢您的详尽解释。因此,我决定根据您的评论选择我的全部答案。现在我打算直接下一个和上一个。至于下一个:我们有 people[(i + 1) % people.length] 工作正常
  • @James 你的问题没有提到任何关于 prev 的内容。如果这是其中的一部分,请更新您的问题...
  • 谢谢你,你赢得了这个问题:)
猜你喜欢
  • 2019-08-31
  • 1970-01-01
  • 2011-06-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
相关资源
最近更新 更多