【Vue2 源码07】patch hook

161 阅读1分钟

patch hook调用时机

patch

patch (oldVnode, vnode, hydrating, removeOnly) {
    if (isUndef(vnode)) {
      if (isDef(oldVnode)) invokeDestroyHook(oldVnode)
      return
    }
    
    createElm()
    
    invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch)
}

createElm

createElm(){
    if (isDef(data)) {
      invokeCreateHooks(vnode, insertedVnodeQueue)
    }
}
function invokeCreateHooks (vnode, insertedVnodeQueue) {
    for (let i = 0; i < cbs.create.length; ++i) {
        cbs.create[i](emptyNode, vnode) // modules create hook
    }
    i = vnode.data.hook // Reuse variable
    if (isDef(i)) {
        if (isDef(i.create)) i.create(emptyNode, vnode)
        if (isDef(i.insert)) insertedVnodeQueue.push(vnode) // 组件存在insert hook
    }
}

invokeInsertHook

function invokeInsertHook (vnode, queue, initial) {
    if (isTrue(initial) && isDef(vnode.parent)) {
        vnode.parent.data.pendingInsert = queue
    } else {
        for (let i = 0; i < queue.length; ++i) {
            queue[i].data.hook.insert(queue[i]) // data insert
        }
    }
}

platformModules

/src/platforms/web/runtime/modules

modules cbs

const hooks = ['create', 'activate', 'update', 'remove', 'destroy']

const { modules, nodeOps } = backend

for (i = 0; i < hooks.length; ++i) {
    cbs[hooks[i]] = []
    for (j = 0; j < modules.length; ++j) {
        if (isDef(modules[j][hooks[i]])) {
            cbs[hooks[i]].push(modules[j][hooks[i]])
        }
    }
}

image.png

attrs.js

function updateAttrs (oldVnode: VNodeWithData, vnode: VNodeWithData) {}

export default {
  create: updateAttrs,
  update: updateAttrs
}

class.js

function updateClass (oldVnode: any, vnode: any) {}

export default {
  create: updateClass,
  update: updateClass
}

dom-props.js

function updateDOMProps (oldVnode: VNodeWithData, vnode: VNodeWithData) {}

export default {
  create: updateDOMProps,
  update: updateDOMProps
}

events.js

function updateDOMListeners (oldVnode: VNodeWithData, vnode: VNodeWithData) {}

export default {
  create: updateDOMListeners,
  update: updateDOMListeners
}

style.js

function updateStyle (oldVnode: VNodeWithData, vnode: VNodeWithData) {}

export default {
  create: updateStyle,
  update: updateStyle
}

style.js

function _enter (_: any, vnode: VNodeWithData) {}

export default inBrowser ? {
  create: _enter,
  activate: _enter,
  remove (vnode: VNode, rm: Function) {
    if (vnode.data.show !== true) {
      leave(vnode, rm)
    } else {
      rm()
    }
  }
} : {}

baseModules

/src/core/vdom/modules

directives.js

function updateDirectives (oldVnode: VNodeWithData, vnode: VNodeWithData) {}

export default {
  create: updateDirectives,
  update: updateDirectives,
  destroy: function unbindDirectives (vnode: VNodeWithData) {
    updateDirectives(vnode, emptyNode)
  }
}

ref.js

export function registerRef (vnode: VNodeWithData, isRemoval: ?boolean) {}

export default {
  create (_: any, vnode: VNodeWithData) {
    registerRef(vnode)
  },
  update (oldVnode: VNodeWithData, vnode: VNodeWithData) {
    if (oldVnode.data.ref !== vnode.data.ref) {
      registerRef(oldVnode, true)
      registerRef(vnode)
    }
  },
  destroy (vnode: VNodeWithData) {
    registerRef(vnode, true)
  }
}