Angular的属性绑定机制不起作用
今天用Kendo UI for Angular的TreeList组件时发现了一个问题: 将一个数组类型的对象data作为TreeList的数据源,当向data中追加新的元素时,画面上TreeList的数据并不会立即刷新;而将data赋值null或者其他新赋值时,TreeList的数据就会立刻刷新。为什么已经将data绑定到TreeList上了,即使data的值发生了变化,画面内容没有立即改变呢?似乎Angular的属性绑定机制没有起作用一样。。
探索
Kendo UI for Angular的TreeList组件有其自己的解决办法,使用FlatBindingDirective.rebind()可以完成刷新的功能。Angular的绑定机制不就是为了让后台改变的内容自动反应到画面上么?为何已经绑定好的东西,实现真正的"绑定"功能却需要其他的方法来辅助完成呢?
关于Angular如何实现数据绑定机制的原理在网上可以搜索到很多资源,这里就不再详细说明了。 简单来说,Angular提供了一个监视器去监视被绑定的变量是否发生变化,如果监视器认为被绑定的变量发生了变化,就会将其反应到绑定该变量的组件上。
那么什么样的情况下才是 监视器认为被绑定的变量发生了变化 了呢?
页面代码
<div>
<input [value]="strTest" />
<button (click)="testFunction1()">testFunction1</button>
</div>
<div>
<input [value]="strTest" />
<button (click)="testFunction2()">testFunction2</button>
</div>
<div>
<input [value]="strTest" />
<button (click)="testFunction3()">testFunction3</button>
</div>
ts代码
export class AppComponent {
public strTest: string[] = ['test1', 'test2', 'test3'];
public testFunction1(): void {
console.log(this.strTest);
this.strTest.push('test4');
console.log(this.strTest);
}
public testFunction2(): void {
console.log(this.strTest);
this.strTest = ['test4'];
console.log(this.strTest);
}
public testFunction3(): void {
console.log(this.strTest);
this.strTest[0] = 'testtest1';
console.log(this.strTest);
}
}
画面: 点击第一个按钮: 点击第二个按钮: 点击第三个按钮:
从以上示例可以看出,所谓Angular监视被绑定的对象变量,其实是监视其堆栈中的值。 对于简单数据类型,堆栈中存放的就是其值,因此一旦变量的值发生了改变,其堆栈中存放的内容就发生了改变,因此Angular的监视器便会捕捉到这一变化从而改变组件上的内容。
对于引用数据类型,堆栈中存放的是指针(引用对象的地址)。 当引用对象的值发生改变时,堆栈中的地址并没有改变,仅仅只是其地址所指向的对象发生了改变。这种情况下,Angular监视器并不认为该对象已经发生了变化,所以并不会刷新组件的内容(上面例子中的按钮一和按钮三); 当引用对象发生改变,如:被赋予了新对象…其堆栈中的地址就发生了改变。这种情况下,Angular监视器就会认为对象发生了变化,进而刷新组件的内容(上面例子中的按钮二)。
|