【问题标题】:Angular2 @Input to a property with get/setAngular2 @Input 到带有 get/set 的属性
【发布时间】:2016-08-07 19:29:26
【问题描述】:

我在该组件中有一个 Angular2 组件,它当前有一堆字段,在它们之前应用了 @Input() 以允许绑定到该属性,即

@Input() allowDay: boolean;

我想要做的实际上是使用 get/set 绑定到一个属性,这样我就可以在 setter 中执行一些其他逻辑,如下所示

_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
set allowDay(value: boolean) {
     this._allowDay = value;
     this.updatePeriodTypes();
}

我将如何在 Angular2 中做到这一点?

根据 Thierry Templier 的建议,我将其更改为,但这会引发错误 Can't bind to 'allowDay' 因为它不是已知的本机属性:

//@Input() allowDay: boolean;
_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
@Input('allowDay') set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}

【问题讨论】:

  • 如何以及在哪里绑定到[allowDay]="....". If the field (setter) name and the property name you want to use for binding are the same, you can omit the parameter for @Input(...)`。
  • 如果您按照接受的答案所示的方式使用 get set,我很想知道您是如何设置单元测试的。
  • 无论您最终做什么,请确保在您的设置器中放置一个断点、调试语句或计数器,以确保它只按预期触发一次。我刚刚发现我的每次更改检测运行都会更新,这会导致糟糕的性能和古怪的行为。

标签: angular


【解决方案1】:

您可以直接在 setter 上设置@Input,如下所述:

_allowDay: boolean;
get allowDay(): boolean {
    return this._allowDay;
}
@Input() set allowDay(value: boolean) {
    this._allowDay = value;
    this.updatePeriodTypes();
}

查看此 Plunkr:https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview

【讨论】:

  • 我收到以下错误无法绑定到“allowDay”,因为它不是已知的本机属性。有关我将代码更改为的确切内容,请参阅更新的问题
  • 你确定吗?这个对我有用。我添加了一个 plunkr。也许您忘记将指令添加到要使用它的组件的 directives 属性中......我更新了我的答案。
  • 这是个坏主意,因为如果您使用 setter,ngOnChanges 不会触发。
  • 警告setter不会由对通过引用传递的值的突变触发(即推送到数组,改变一个对象等)。您需要替换作为Input 传递的整个值,以便setter 再次触发。
【解决方案2】:

@Paul Cavacas,我​​遇到了同样的问题,我通过在 getter 上方设置 Input() 装饰器来解决。

  @Input('allowDays')
  get in(): any {
    return this._allowDays;
  }

  //@Input('allowDays')
  // not working
  set in(val) {
    console.log('allowDays = '+val);
    this._allowDays = val;
  }

查看此插件:https://plnkr.co/edit/6miSutgTe9sfEMCb8N4p?p=preview

【讨论】:

【解决方案3】:

如果您的主要兴趣是仅对 setter 实现逻辑

import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';

// [...]

export class MyClass implements OnChanges {
  @Input() allowDay: boolean;

  ngOnChanges(changes: SimpleChanges): void {
    if(changes['allowDay']) {
      this.updatePeriodTypes();
    }
  }
}

如果更改了哪个输入属性无关紧要,或者您只有一个输入属性,则不需要导入SimpleChanges

Angular Doc: OnChanges

否则:

private _allowDay: boolean;

@Input() set allowDay(value: boolean) {
  this._allowDay = value;
  this.updatePeriodTypes();
}
get allowDay(): boolean {
  // other logic
  return this._allowDay;
}

【讨论】:

  • 只是好奇,如果您只对 setter 逻辑感兴趣,那么使用 ngOnChanges 与不使用 set 属性有什么好处?
  • “使用 ngOnChanges 与不使用 set”没有区别... ;) 开个玩笑:一个好处是,如果您的组件有多个 @Input 属性并且您想在以下情况下调用例程其中任何一个都发生了变化。所以需要更少的代码。
  • Ups,打错字了,呵呵。但是,好吧,认为它可能有更多的相关性。谢谢你的回答:)
  • ngOnChanges 方法很棒!!好答案。如果设置的值不能是私有的,例如它在模板中用作绑定,_propertyName setter/private 命名约定变得不一致。 ngOnChanges 完美地解决了这个问题
【解决方案4】:

在此处更新了 stackblitz 上 Angular 7.0.1 的已接受答案:https://stackblitz.com/edit/angular-inputsetter?embed=1&file=src/app/app.component.ts

directives 不再出现在组件装饰器选项中。所以我为 app 模块提供了子指令。

谢谢@thierry-templier

【讨论】:

    猜你喜欢
    • 2015-09-03
    • 2019-02-23
    • 2012-05-11
    • 2015-08-19
    • 2013-10-24
    • 2010-09-19
    • 2021-01-08
    • 1970-01-01
    • 2012-04-05
    相关资源
    最近更新 更多