Child组件有两个数据绑定输入属性,一个是类型错误string
(inputVariable
),另一个是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将其识别为更改。