你可能已经很熟悉 [(ngModel)] 以及它著名的香蕉盒子语法。这篇文章,我将会介绍ngModel
是如何工作的,这有助于我们复现它的行为并实现我们自己的双向数据绑定。
现在,我们来创建一个message
作为参数的组件,这个message
就是该组件的model
,我们将这样使用这个组件:
<example-component
[(message)]="title"
></example-component>
上面高亮的代码就是我们要实现的双向数据绑定。
首先,我们来剖析一下应用于ngModel
上的香蕉盒子语法。下面是我们都知道的语法:
<input [(ngModel)]="title" type="text">
有趣的是[()]
其实是下面这段代码的语法糖:
<input [ngModel]="title" (ngModelChange)="title= $event" type="text">
这段代码无疑更冗长,但却让人更容易理解,双向数据绑定其实就是两个单向数据绑定。
这个例子揭露的真相就是Change
后缀的用法,让我们在自己的样例组件中使用这个技巧吧。
首先,我们创建一个带有 @Input
单向数据绑定的组件:
export class TwoWayDataBindingExampleComponent {
messageValue : string;
@Input()
get message(){
return this.messageValue;
}
set message(val) {
this.messageValue = val;
}
}
这里有两个值得注意的地方,首先我用 messageValue
来存储实际的信息,然后用message
来暴露它,所以我可以用 TypeScript 的 getters
和setters
来读取messageValue
的值。
这是该技术关键的一步,因为一旦model 改变了,需要 setter 做很多工作来通知其他的组件。
下面就是我们实现第二次单向数据绑定的方法:
export class TwoWayDataBindingExampleComponent {
messageValue : string;
@Output()
messageChange = new EventEmitter<string>();
@Input()
get message(){
return this.messageValue;
}
set message(val) {
this.messageValue = val;
this.messageChange.emit(this.messageValue);
}
}
现在万事俱备了,getter
和setter
都使用messageValue
来读取或更新数据模型,而且setter
还通过 emit 事件通知其他的组件。
结果我们可以看到组件中应用的一个双向数据绑定语法如下:
<example-component [(message)]="title"></example-component>
很简单吧,只要我们知道其中的技巧,就可以在组件中实现我们自己的双向数据绑定了。
网友评论