Component HTML:

   <input type="text" maxlength="40" nz-input placeholder="Input Book Name to search" [(ngModel)] ="bookName" (keyup) ="search(bookName)"
    />
Copy the code

The bookName is a Component property:

Runtime render to template containing [(ngModel)] :

Create a directive instance:



Create ngModel instance:

If I type an A in the UI, the Component’s bookName value will also be a because of bidirectional binding.

This function executes checkhooks whenever the refreshView redraw interface is triggered by a UI change:

/**
 * Executing hooks requires complex logic as we need to deal with 2 constraints.
 *
 * 1. Init hooks (ngOnInit, ngAfterContentInit, ngAfterViewInit) must all be executed once and only
 * once, across many change detection cycles. This must be true even if some hooks throw, or if
 * some recursively trigger a change detection cycle.
 * To solve that, it is required to track the state of the execution of these init hooks.
 * This is done by storing and maintaining flags in the view: the {@link InitPhaseState},
 * and the index within that phase. They can be seen as a cursor in the following structure:
 * [[onInit1, onInit2], [afterContentInit1], [afterViewInit1, afterViewInit2, afterViewInit3]]
 * They are are stored as flags in LView[FLAGS].
 *
 * 2. Pre-order hooks can be executed in batches, because of the select instruction.
 * To be able to pause and resume their execution, we also need some state about the hook's array
 * that is being processed:
 * - the index of the next hook to be executed
 * - the number of init hooks already found in the processed part of the  array
 * They are are stored as flags in LView[PREORDER_HOOK_FLAGS].
 */
/**
 * Executes pre-order check hooks ( OnChanges, DoChanges) given a view where all the init hooks were
 * executed once. This is a light version of executeInitAndCheckPreOrderHooks where we can skip read
 * / write of the init-hooks related flags.
 * @param {? } lView The LView where hooks are defined
 * @param {? } hooks Hooks to 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))
 * @return {? }* /
function executeCheckHooks(lView, hooks, nodeIndex) {
    callHooks(lView, hooks, 3 /* InitPhaseCompleted */, nodeIndex);
}
Copy the code

Function wrapOnChangesHook_inPreviousChangesStorage:

functionɵ ɵNgOnChangesFeature(definition) {
    if (definition.type.prototype.ngOnChanges) {
        definition.setInput = ngOnChangesSetInput;
        ((/ * *@type {? } * /(definition))).onChanges = wrapOnChanges(); }}// This option ensures that the ngOnChanges lifecycle hook will be inherited
// from superclasses (in InheritDefinitionFeature).
/ * *@nocollapse * /
// tslint:disable-next-line:no-toplevel-property-access
((/ * *@type {? } * /(ɵ ɵ NgOnChangesFeature))). NgInherit =true;
/ * * *@return {? }* /
function wrapOnChanges() {
    return (/ * * *@this {? }
     * @return {? }* /
    function wrapOnChangesHook_inPreviousChangesStorage() {
        / * *@type {? } * /
        const simpleChangesStore = getSimpleChangesStore(this);
        / * *@type {? } * /
        const current = simpleChangesStore && simpleChangesStore.current;
        if (current) {
            / * *@type {? } * /
            const previous = (/ * *@type {? } * / (simpleChangesStore)).previous;
            if (previous === EMPTY_OBJ) {
                (/ * *@type {? } * / (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 incurrent) { previous[key] = current[key]; }} (/ * *@type {? } * / (simpleChangesStore)).current = null;
            this.ngOnChanges(current); }}); }Copy the code

/**
 * Wraps an event listener with a function that marks ancestors dirty and prevents default behavior,
 * if applicable.
 *
 * @param {? } tNode The TNode associated with this listener
 * @param {? } lView The LView that contains this listener
 * @param {? } listenerFn The listener function to call
 * @param {? } wrapWithPreventDefault Whether or not to prevent default behavior
 * (the procedural renderer does this already, so in those cases, we should skip)
 * @return {? }* /
function wrapListener(tNode, lView, listenerFn, wrapWithPreventDefault) {
    // Note: we are performing most of the work in the listener function itself
    // to optimize listener registration.
    return (/ * * *@param {? } e
     * @return {? }* /
    function wrapListenerIn_markDirtyAndPreventDefault(e) {
        // Ivy uses `Function` as a special token that allows us to unwrap the function
        // so that it can be invoked programmatically by `DebugNode.triggerEventHandler`.
        if (e === Function) {
            return listenerFn;
        }
        // In order to be backwards compatible with View Engine, events on component host nodes
        // must also mark the component view itself dirty (i.e. the view that it owns).
        / * *@type {? } * /
        const startView = tNode.flags & 2 /* isComponentHost */ ?
            getComponentLViewByIndex(tNode.index, lView) :
            lView;
        // See interfaces/view.ts for more on LViewFlags.ManualOnPush
        if ((lView[FLAGS] & 32 /* ManualOnPush */) = = =0) {
            markViewDirty(startView);
        }
        / * *@type {? } * /
        let result = executeListenerWithErrorHandling(lView, listenerFn, e);
        // A just-invoked listener function might have coalesced listeners so we need to check for
        // their presence and invoke as needed.
        / * *@type {? } * /
        let nextListenerFn = ((/ * *@type {? } * / (wrapListenerIn_markDirtyAndPreventDefault))).__ngNextListenerFn__;
        while (nextListenerFn) {
            // We should prevent default if any of the listeners explicitly return false
            result = executeListenerWithErrorHandling(lView, nextListenerFn, e) && result;
            nextListenerFn = ((/ * *@type {? } * / (nextListenerFn))).__ngNextListenerFn__;
        }
        if (wrapWithPreventDefault && result === false) {
            e.preventDefault();
            // Necessary for legacy browsers that don't support preventDefault (e.g. IE)
            e.returnValue = false;
        }
        return result;
    });
}
Copy the code

Go to forms.js _handleInput(value):



For more of Jerry’s original articles, please follow the public account “Wang Zixi “: