Angular property binding重复触发的问题讨论

112 阅读1分钟

Component template文件源代码:

<button [disabled]="isDisabled" >Click me</button>

Component实现:

export class AppComponent implements OnInit {

  counter = 0;
  get isDisabled(){
    console.log('Jerry: ' + this.counter++);
    return true;
  }
}

Component里维护了一个计数器:counter

运行时的输出:

下面是分别研究这四次get调用的上下文。

第一次触发

通过_loadComponent触发:

第二次触发

同第一次触发一样,同样是在tick方法里,只不过第一次触发在tick的view.detectChanges里,而第二次触发,在view.checkNoChanges里:

/**
     * Invoke this method to explicitly process change detection and its side-effects.
     *
     * In development mode, `tick()` also performs a second change detection cycle to ensure that no
     * further changes are detected. If additional changes are picked up during this second cycle,
     * bindings in the app have side-effects that cannot be resolved in a single change detection
     * pass.
     * In this case, Angular throws an error, since an Angular application can only have one change
     * detection pass during which all change detection must complete.
     * @return {?}
     */

第三次触发

class ApplicationRef {
    /**
     * \@internal
     * @param {?} _zone
     * @param {?} _console
     * @param {?} _injector
     * @param {?} _exceptionHandler
     * @param {?} _componentFactoryResolver
     * @param {?} _initStatus
     */
    constructor(_zone, _console, _injector, _exceptionHandler, _componentFactoryResolver, _initStatus) {
        this._zone = _zone;
        this._console = _console;
        this._injector = _injector;
        this._exceptionHandler = _exceptionHandler;
        this._componentFactoryResolver = _componentFactoryResolver;
        this._initStatus = _initStatus;
        /**
         * \@internal
         */
        this._bootstrapListeners = [];
        this._views = [];
        this._runningTick = false;
        this._enforceNoNewChanges = false;
        this._stable = true;
        /**
         * Get a list of component types registered to this application.
         * This list is populated even before the component is created.
         */
        this.componentTypes = [];
        /**
         * Get a list of components registered to this application.
         */
        this.components = [];
        this._enforceNoNewChanges = isDevMode();
        this._zone.onMicrotaskEmpty.subscribe({
            next: (/**
             * @return {?}
             */
            () => {
                this._zone.run((/**
                 * @return {?}
                 */
                () => {
                    this.tick();
                }));
            })
        });

第四次也是最后一次触发

更多Jerry的原创文章,尽在:“汪子熙”: