Vue 的父子组件生命周期钩子函数执行顺序
- 渲染顺序 :先父后子,完成顺序:先子后父
- 更新顺序 :父更新导致子更新,子更新完成后父
- 销毁顺序 :先父后子,完成顺序:先子后父
加载渲染过程
父 beforeCreate
->父 created
->父 beforeMount
->子 beforeCreate
->子 created
->子 beforeMount
->子 mounted
->父 mounted
。子组件先挂载,然后到父组件
子组件更新过程
父 beforeUpdate
->子 beforeUpdate
->子 updated
->父 updated
父组件更新过程
父 beforeUpdate
->父 updated
销毁过程
父 beforeDestroy
->子 beforeDestroy
->子 destroyed
->父 destroyed
之所以会这样是因为
Vue
创建过程是一个递归过程,先创建父组件,有子组件就会创建子组件,因此创建时先有父组件再有子组件;子组件首次创建时会添加mounted
钩子到队列,等到patch
结束再执行它们,可见子组件的mounted
钩子是先进入到队列中的,因此等到patch
结束执行这些钩子时也先执行。
function patch (oldVnode, vnode, hydrating, removeOnly) {
if (isUndef(vnode)) {
if (isDef(oldVnode)) invokeDestroyHook(oldVnode) return
}
let isInitialPatch = false
const insertedVnodeQueue = [] // 定义收集所有组件的insert hook方法的数组 // somthing ...
createElm(
vnode,
insertedVnodeQueue, oldElm._leaveCb ? null : parentElm,
nodeOps.nextSibling(oldElm)
)// somthing...
// 最终会依次调用收集的insert hook
invokeInsertHook(vnode, insertedVnodeQueue, isInitialPatch);
return vnode.elm
}
function createElm ( vnode, insertedVnodeQueue, parentElm, refElm, nested, ownerArray, index ) {
// createChildren 会递归创建儿子组件
createChildren(vnode, children, insertedVnodeQueue) // something...
}
// 将组件的vnode插入到数组中
function invokeCreateHooks (vnode, insertedVnodeQueue) {
for (let i = 0; i < cbs.create.length; ++i) {
cbs.create[i](emptyNode, vnode)
}
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方法中会依次调用mounted方法
insert (vnode: MountedComponentVNode) {
const {
context, componentInstance } = vnode
if (!componentInstance._isMounted) {
componentInstance._isMounted = true
callHook(componentInstance, 'mounted')
}
}
function invokeInsertHook (vnode, queue, initial) {
// delay insert hooks for component root nodes, invoke them after the // element is really inserted
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]); // 调用insert方法
}
}
}
Vue.prototype.$destroy = function ()