天天看点

fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子

is._tick里调用this.changeDetectorRef.detectChanges():

fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
首先从RootViewRef开始检测:
fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
context里能看到Component的数据:
fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
renderComponentOrTemplate:
fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
refreshView里会调用init和check hook:
fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子

/**
 * Executes post-order init and check hooks (one of AfterContentInit, AfterContentChecked,
 * AfterViewInit, AfterViewChecked) given a view where there are pending init hooks to be executed.
 * @param lView The LView where hooks are defined
 * @param hooks Hooks to be run
 * @param initPhase A phase for which hooks should be run
 * @param nodeIndex 3 cases depending on the value:
 * - undefined: all hooks from the array should be executed (post-order case)
 * - null: execute hooks only from the saved index until the end of the array (pre-order case, when
 * flushing the remaining hooks)
 * - number: execute hooks only from the saved index until that node index exclusive (pre-order
 * case, when executing select(number))
 */
function executeInitAndCheckHooks(lView, hooks, initPhase, nodeIndex) {
    ngDevMode &&
        assertNotEqual(initPhase, 3 /* InitPhaseCompleted */, 'Init pre-order hooks should not be called more than once');
    if ((lView[FLAGS] & 3 /* InitPhaseStateMask */) === initPhase) {
        callHooks(lView, hooks, initPhase, nodeIndex);
    }
}
      

使用Directive实例调用hook:

fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子
function rememberChangeHistoryAndInvokeOnChangesHook() {
    const simpleChangesStore = getSimpleChangesStore(this);
    const current = simpleChangesStore === null || simpleChangesStore === void 0 ? void 0 : simpleChangesStore.current;
    if (current) {
        const previous = simpleChangesStore.previous;
        if (previous === EMPTY_OBJ) {
            simpleChangesStore.previous = current;
        }
        else {
            // New changes are copied to the previous store, so that we don't lose history for inputs
            // which were not changed this time
            for (let key in current) {
                previous[key] = current[key];
            }
        }
        simpleChangesStore.current = null;
        this.ngOnChanges(current);
    }
}
      

ngOnChanged hook被调用的前提是,从getSimpleChangesStore返回的simpleChangesStore里的current字段不为空:

fixture.detectChange开始单步调试,如何执行到Directive的ngOnChange钩子

继续阅读