【问题标题】:Angular - Two way binding input property to component with getters / settersAngular - 使用getter / setter将输入属性两种方式绑定到组件
【发布时间】:2020-10-13 10:20:41
【问题描述】:

我有以下角度组件:

ComponentB 具有输入属性,componentA 在模板文件中插入 componentB。 代码如下:

componentA.ts:

export class ComponentA{
    isOpen: boolean;

    methodA() {
        this.isOpen = false;
        // do some work
    }
}

组件A.html:

<componentB [(open)]="isOpen"></componentB >

ComponentB.ts:

@Component({
    selector: 'componentB',
    templateUrl: 'ComponentB .html',
    encapsulation: ViewEncapsulation.None,
})
export class ComponentB {

    private _open: boolean = false;

    @Input('open') set open(value: boolean) {
        if (open === this._open) {
            return;
        }
        if (open) {
            // doSomething()
        } else {
            // doSomethingElse()
        }
        this._open = open;
    }

    get open() {
        return this._open;
    }
}

问题是isOpen 属性似乎没有反映open 属性的当前值,尽管指定了两种方式绑定。

为什么会这样? 怎么解决?

【问题讨论】:

    标签: angular getter-setter property-binding


    【解决方案1】:

    双向绑定是 Angular 提供的一种特殊语法,用于同时设置组件的值和监听值的变化。

    为此,使用了特殊语法(盒装香蕉)“[()]”。请查找有关此here 的官方 Angular 文档。

    简而言之,您必须提供一个带有 @Input() 装饰器的属性,以及一个带有 @Output() 装饰器的属性。 @Output() 属性将附加单词 Change。因此,如果@Input 属性名称为 x,则输出属性名称应为 xChange。并且每当底层绑定属性发生变化时,使用输出属性的EventEmitter,让父组件监听变化(因此实现了两种方式的绑定)。

    在您的情况下,您的代码会像这样更新

      @Input('open') set open(value: boolean) {
            if (value === this._open) {
                return;
            }
            if (open) {
                // doSomething()
            } else {
                // doSomethingElse()
            }
            this._open = value;
            this.openChange.emit(this._open); //open value set, the updated value is emitted using the output property.
        }
        get open() {
            return this._open;
        }
          @Output('openChange')  //the output property added
          openChange = new EventEmitter<boolean>();

    请找到Stack Blitz 链接。

    【讨论】:

      【解决方案2】:
      private _open= false;
      
      @Input('open') set open(value: boolean) {
          if (value=== this._open) {
              return;
          }
          if (value) {
              // doSomething()
          } else {
              // doSomethingElse()
          }
          this._open = value;
      }
      
      get open() {
          return this._open;
      }
      

      你可以试试这个吗?

      顺便说一句 @Input() 打开 : boolean = false;是一个 lint 错误。当您将 = false 分配给值时,它的类型将自动分配为布尔值,您不必指定它

      【讨论】:

      • Tnx!但是 w当我从 componentA 访问 isOpen 的值时(在视图初始化之后)它的值仍然是未定义的
      • 为什么不使用输出? @Output() onValueChange : EventEmitter&lt;boolean&gt; = new EventEmitter(); private _open= false; @Input('open') set open(value: boolean) { if (value=== this._open) { return; } if (value) { // doSomething() } else { // doSomethingElse() } this._open = value; this.onValueChange.emit(value); } get open() { return this._open; } 组件A html &lt;componentB [(open)]="isOpen" (onValueChange)="methodHere($event)"&gt;&lt;/componentB &gt; 组件A .ts onValueChange(open: boolean){ }
      • 如果你想避免子组件中的未定义,你应该检查输入是否等于设置器中的未定义。也许您将 undefined 作为变量发送给子组件,因此它不能将其作为默认变量,而是将 undefined 作为变量。 @Input('open') set open(value: boolean) { if(value !== undefined){ if (value=== this._open) { return; } if (value) { // doSomething() } else { // doSomethingElse() } this._open = value; } }
      • 对于 else 块你应该等于 _open 为 false
      猜你喜欢
      • 2017-03-13
      • 2022-07-31
      • 2016-12-19
      • 2017-08-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-10
      • 1970-01-01
      相关资源
      最近更新 更多