Angular2 two-way data binding

What is a two-way binding

Figure:

 
Two-way binding .jpg

Two-way binding mechanism to maintain the consistency of the page (View) and the data (Data) is. Today, MVVM framework is already an integral part of the popular front section.

The two-way binding Angular2

Two-way binding, two-way binding is one of the core concepts of Angular2, Angular2 is this:

  • data => view: data binding, template syntax is []
  • view => data: event binding, template syntax is ()
  • Angular did not actually implement a two-way binding, and his two-way data binding is binding + event binding , template syntax is [()].

Angular2 official for example:

<!--value是数据绑定,input是事件绑定-->
<input [value]="currentHero.name" (input)="currentHero.name=$event.target.value" > <!--等价--> <input [(ngModel)]="currentHero.name"> 

The above is a two-way binding syntax input space, clearly it illustrates the relationship between the two-way binding with two-way binding. There is no use of ngModulegrammar, ngModuleinternal syntax to achieve with this almost.

Event binding

  1. User Action departure DOM event notification
  2. Angular listening to the notification, then perform template syntax, the above example is to input input values assigned to the control currentHero.name.

Data Binding

Due to language and not js property change notification mechanism, so the angular do not know who has changed, at what time has changed. Angular change mechanism are:

 
image.png

Binding process input data examples above is as follows:

  1. Modify the code currentHero.namevalue.
  2. Check the whole trigger changes in the component tree.
  3. the input display the modified value.
When data changes

The main focus into the next situation may change the data:

  • User input operations, such as click, submit and so on.
  • The server request data.
  • Timed events, such as setTimeout, setInterval.

These points have in common is that they are asynchronous. That is, all the asynchronous operation is the root factors that could cause changes in the data.

How to change notification

In Angularjs it is by the code $scope.$apply()or $scope.$digesttrigger, but the Angular2 access ZoneJS, which it is listening Angular all asynchronous events. ZoneJS rewrite all the asynchronous API (the so-called monkey patch, MonkeyPath). ZoneJS will notify Angular may have data changes, you need to check for updates.

Change detection principle - dirty check

The so-called dirty check value is stored in all the variables, whenever there may need to check when variables change, it will be the old value with the new values ​​of all variables are compared are not equal it means a change is detected, it is necessary to update the corresponding view.

AngularJS difference and change detection Angular2

Angularjs change detection mechanism is dirty check, change detection performance Angular2's improved a lot than Angularjs.

Angular2

Angular assembly of the core, such that the nested components will ultimately form an assembly tree. Angular change detection can be divided components, each component has a corresponding change detector ChangeDetector. One can imagine, these will constitute a change detector tree.

Further, the Angular the data stream is a top-down from the parent component subassembly to unidirectional flow. One-way data flow to ensure efficient and predictable change detection, although examined after negative component, component data may change from the parent component assembly such that the parent needs to be checked again, this is not recommended data processing. In development mode, Angular secondary inspection will be carried out, if this occurs, double-check the error will be: ExpressionChangedAfterItHasBeenCheckedError(answers to this question can be found in Resources). In a production environment, dirty checked only once.

AngularJS

In contrast, Angularjs uses a two-way data flow, complex data streams so that he had to check several times, so that data eventually becoming stable. In theory, the data can never be stable, Angularjs strategy is more than 10 times dirty checking procedures to identify the problem.

 
angular2-change-detection-moscowjs-31-9-638.jpg

Change detection Optimization

Optimization Strategy

There are two ideas:

  1. OnPush strategy: I know I have not changed, I do not check.
  2. 手动控制刷新:我变了,只查我。

变化检测策略 OnPush

Angular还让开发者拥有制定变化策略的能力。

export enum ChangeDetectionStrategy { 
  OnPush, // 表示变化检测对象的状态为`CheckOnce` 
  Default, // 表示变化检测对象的状态为`CheckAlways`
}

ChangeDetectionStrategy可以看到,Angular有两种变化检测策略。Default是Angular默认的变化检测策略,也就是脏检查(只要有值发生变化,就全部检查)。开发者可以根据场景来设置更加高效的变化检测方式:OnPushOnPush策略,就是只有当输入数据的引用发生变化或者有事件触发时,组件进行变化检测。

@Component({
  template: `
    <h2>{{vData.name}}</h2>
    <span>{{vData.email}}</span>
  `,
  // 设置该组件的变化检测策略为onPush
  changeDetection: ChangeDetectionStrategy.OnPush
})
class VCardCmp {
  @Input() vData; } 

比如上面这个例子,当vData的属性值发生变化的时候,这个组件不会发生变化检测,只有当vData重新赋值的时候才会。一般,只接受输入的木偶子组件(dumb components)比较适合采用onPush策略。

那什么时候只要对象的属性值发生变化,整个对象的引用就变了呢?不可变对象(Immutable Object)。当组件中的输入对象是不变量时,可采用onPush变化检测策略,减少变化检测的频率。换个角度来说,为了更加智能地执行变化检测,可以在只接受输入的子组件中采用onPush策略。

手动控制变化检测

Angular不仅可以让开发者设置变化检测策略,还可以让开发者获取变化检测对象引用ChangeDetectorRef,手动去操作变化检测。变化检测对象引用给开发者提供的方法有以下几种:

  • markForCheck():将检查组件的所有父组件所有子组件,即使设置了变化检测策略为onPush
  • detach():将变化检测对象脱离检测对象树,不再进行变化检查;结合detectChanges可实现局部变化检测。(采用onPush策略之后的组件detach()无效)
  • detectChanges():将检测该组件及其子组件,结合detach可实现局部检测。
  • checkNoChanges(): 检测该组件及其子组件,如果有变化存在则报错,用于开发阶段二次验证变化已经完成。
  • reattach():将脱离的变化检测对象重新链接到变化检测树上。

那么,如果是Observable的话,它会订阅所有的变量变化,只要在订阅回调函数中手动触发变化检测即可实现最小成本的检测(仍采用onPush变化检测策略)。举个例子:

@Component({
  template: '{{counter}}',
  changeDetection: ChangeDetectionStrategy.OnPush
})
class CartBadgeCmp {

  @Input() addItemStream:Observable<any>; counter = 0; constructor(private cd: ChangeDetectorRef) {} ngOnInit() { this.addItemStream.subscribe(() => { this.counter++; // 数据模型发生变化 this.cd.markForCheck(); // 手动触发检测 }) } } 

另外,当数据模型变化太过频繁,我们可自定义变化检测的时机。举个例子:

@Component({
  template: `{{counter}}
  <input type="check" (click)="toggle()">`, 
})
class CartBadgeCmp { 
  counter = 0;
  detectEnabled = false; constructor(private cd: ChangeDetectorRef) {} ngOnInit() { // 每10毫秒增加1 setInterval(()=>{this.counter++}, 10); } toggle(){ if( this.detectEnabled ){ this.cd.reattach(); // 链接上变化检测树 } else{ this.cd.detach(); // 脱离变化检测树 } } } 

总结

Angular与Angularjs都采用变化检测机制,前者优于后者主要体现在:

  • 单项数据流动
  • 以组件为单位维度独立进行检测
  • 生产环境只进行一次检查
  • 可自定义的变化检测策略:DefaultonPush
  • 可自定义的变化检测操作:markForcheck()detectChanges()detach()reattach()checkNoChanges()
  • 代码实现上的优化,据说采用了VM friendly的代码。




链接:https://www.jianshu.com/p/cee44e8831c9

Guess you like

Origin www.cnblogs.com/ckAng/p/11057712.html