Angular 2中的组件间属性绑定



Child组件有两个数据绑定输入属性,一个是类型错误stringinputVariable),另一个是string[]inputArray)。

import {Component, Inject, Input} from 'angular2/core';
@Component(
{
    selector: 'child-app',
    template: `
    {{inputVariable}}
    <input type="button" (click)="onButtonOneClick()" value="changeFoo">
    <ul>
      <li *ngFor="#el of inputArray"> {{el}} </li>
    </ul>        
    <input type="button" (click)="onButtonTwoClick()" value="ChangeLi">       
    `
})
export class ChildAppComponent {
  @Input() inputVariable: string;
  @Input() inputArray: string[];
  onButtonOneClick() {
    this.inputVariable = 'new string';
  }
  onButtonTwoClick() {
    this.inputArray[0] = 'New element String';
  } 
}

父组件具有相同的属性,并在模板([inputArray]="inputArray" inputVariable="inputVariable")内初始化子组件对应的属性

import {Component} from 'angular2/core';
import {ChildAppComponent} from './childApp.component';
@Component({
selector: 'my-app',
template:
`
{{inputVariable}}
    <input type="button" (click)="onButtonOneClick()" value="changeFoo">
    <ul>
      <li *ngFor="#el of inputArray"> {{el}} </li>
    </ul>        
    <input type="button" (click)="onButtonTwoClick()" value="ChangeLi"> 
   <hr>    
    <child-app [inputArray]="inputArray" inputVariable="inputVariable"> </child-app>
  `,
  directives: [ChildAppComponent]
  })
 export class AppComponent {
   inputVariable: string = 'foo';
   inputArray: string[] = ['one', 'two'];
   onButtonOneClick() {
       this.inputVariable = 'new string';
   }
   onButtonTwoClick() {
      this.inputArray[0] = 'New element String';
   }
}

父组件和子组件内部的按钮单击会更改相应属性(buttonOne->inputVariable&buttonTwo->inputArray)的值

当点击第二个按钮(更改string[]属性值)时,父组件和子组件都会发生更改

当单击第一个按钮(更改string属性值)时,只有更改发生在父级或子级(与我单击的组件按钮相对应)内

  • 为什么行为因财产类型而异
  • 如何在子组件和父组件的string属性之间进行双向绑定

使用输入,如果希望父组件看到更新,则只能通过引用进行更改。数组是这种情况,但字符串属性(以及更常见的具有基元类型的属性)不是这样。

要使每种情况都有效,您需要利用输出和双向绑定:

@Component({
  (...)
})
export class ChildAppComponent {
  @Input() inputVariable: string;
  @Output() inputVariableChange: EventEmitter<string> = new EventEmitter();
  @Input() inputArray: string[];
  onButtonOneClick() {
    this.inputVariable = 'new string';
    this.inputVariableChange.emit(this.inputVariable);
  }
  (...)
}

这可以通过以下方式从父组件使用:

<child-app [inputArray]="inputArray"
           [(inputVariable)]="inputVariable"> </child-app>

请参阅[(...])语法。在这种情况下,当此属性的子组件中发生更新时,inputVariable将透明地更新。

您可以注意到,Angular2仅在绑定的引用发生更改时检测更改,而不是在更新相应的内容(对象属性或数组中的元素)时检测更改。

这是默认行为,但您可以基于DoCheck接口提供自己的行为。请参阅这个用例的问题:

  • Angular2刷新阵列推送视图

从子级到父级的绑定需要使用@Output()

双向绑定

import {Component, Inject, Input} from 'angular2/core';
@Component({
    selector: 'child-app',
    template: `
    {{inputVariable}}
    <input type="button" (click)="onButtonOneClick()" value="changeFoo">
    <ul>
      <li *ngFor="#el of inputArray"> {{el}} </li>
    </ul>        
    <input type="button" (click)="onButtonTwoClick()" value="ChangeLi">       
    `
})
export class ChildAppComponent {
  @Input() inputVariable: string;
  // v added
  @Output() inputVariableChange:EventEmitter<string> = new EventEmitter<string>();
  @Input() inputArray: string[];
  // v added
  @Output() inputArrayChange:EventEmitter<string[]> = new EventEmitter<string[]>();
  onButtonOneClick() {
    this.inputVariable = 'new string';
    this.inputVariableChange.emit(this.inputVariable);
  }
  onButtonTwoClick() {
    this.inputArray[0] = 'New element String';
    this.inputArrayChange.emit(this.inputArray);
  } 
}

在家长使用它像

{{inputVariable}}
    <input type="button" (click)="onButtonOneClick()" value="changeFoo">
    <ul>
      <li *ngFor="#el of inputArray"> {{el}} </li>
    </ul>        
    <input type="button" (click)="onButtonTwoClick()" value="ChangeLi"> 
   <hr>    
    <!-- v added ( )
    <child-app [(inputArray)]="inputArray" inputVariable="inputVariable"> </child-app>

命名是相关的。快捷方式绑定语法[(xxx)]="yyy"仅在输入和输出分别命名为@Input() xxx@Output() xxxChange时有效。否则必须使用长形式。

[xxx]="zzz" (xxxChange)="zzz = $event"

变化检测

Angular不检查对象或数组内部的更改,它只检查对象或阵列是否与以前不同。

如果只修改了对象的一个属性,或者只添加/删除/替换了一个元素,Angular就不会注意到这一点——例如在类似*ngFor的中

<ul>
  <li *ngFor="#el of inputArray"> {{el}} </li>
</ul>        

如果绑定到一个属性而不仅仅是元素项,则*ngFor会识别更改

<ul>
  <li *ngFor="#el of inputArray"> {{el.someProp}} </li>
</ul>        

例如,一种变通方法是创建一个新的阵列

this.inputArray.slice();

或者使用新的(β2)trackBy特征
另请参阅http://www.bennadel.com/blog/3020-understanding-object-identity-with-ngfor-loops-in-angular-2-beta-3.htm

创建一个副本(新的和不同的数组),Angular将其识别为更改。

最新更新