Angular2 @Input 到带有 get/set 的属性

Posted

技术标签:

【中文标题】Angular2 @Input 到带有 get/set 的属性【英文标题】:Angular2 @Input to a property with 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,我很想知道您是如何设置单元测试的。 无论您最终做什么,请确保在您的设置器中放置一个断点、调试语句或计数器,以确保它只按预期触发一次。我刚刚发现我的每次更改检测运行都会更新,这会导致糟糕的性能和古怪的行为。 【参考方案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 不会触发。 On angular Fundamentals pages 警告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

【讨论】:

这个bug让我抓狂,我终于发现你应该先定义Input()(getter或setter但输入装饰器必须先行) 这里有其他可能有帮助的参考资料 https://github.com/angular/angular/issues/5477【参考方案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!

【讨论】:

以上是关于Angular2 @Input 到带有 get/set 的属性的主要内容,如果未能解决你的问题,请参考以下文章

带有引导事件的 Angular2 不会触发可观察到的变化

如何使用angular2中的mat-input来汇总在mat-table列中输入的值

angular2 @input - 变化检测

带有预填充数据的 Angular2 表单验证

使用带有 Angular2 的scanner-js

3Angular2 Input