Angular 2中的组件间属性绑定

时间:2016-04-01 10:19:56

标签: angular typescript data-binding

子组件有两个数据绑定输入属性,一个是错字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 - &gt; inputVariable&amp; buttonTwo - &gt; inputArray

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

点击第一个按钮(更改string属性值)时,更改在父母或子女内部发生(相应于我点击的组件按钮)

  • 为什么基于属性类型的行为会有所不同?
  • 如何在子组件和父组件string属性之间进行双向绑定?

2 个答案:

答案 0 :(得分:4)

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

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

@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界面提供自己的行为。针对此用例,请参阅此问题:

答案 1 :(得分:1)

对于从子级到父级的绑定,您需要使用@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();

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

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