Vue.js 父子组件生命周期调用顺序
问题
Vue
父子组件生命周期调用顺序
过程理解
加载渲染过程
父beforeCreate
-> 父created
-> 父beforeMount
-> 子beforeCreate
-> 子created
-> 子beforeMount
-> 子mounted
-> 父mounted
子组件更新过程
父beforeUpdate
-> 子beforeUpdate
-> 子updated
-> 父updated
父组件更新过程
父beforeUpdate
-> 父updated
销毁过程
父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed
答案
组件的调用顺序都是先父后子,渲染完成的顺序肯定是先子后父
组件的销毁操作是先父后子,销毁完成的顺序是先子后父
对应源码
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 () {
callHook(vm, 'beforeDestroy') //
// invoke destroy hooks on current rendered tree
vm.__patch__(vm._vnode, null) // 先销毁儿子
// fire destroyed hook
callHook(vm, 'destroyed')
}
更多面试题
如果你想了解更多的前端面试题,可以查看本站的WEB前端面试题 ,这里基本包涵了市场上的所有前端方面的面试题,也有一些大公司的面试图,可以让你面试更加顺利。
面试题 | ||
---|---|---|
HTML | CSS | JavaScript |
jQuery | Vue.js | React |
算法 | HTTP | Babel |
BootStrap | Electron | Gulp |
Node.js | 前端经验相关 | 前端综合 |
Webpack | 微信小程序 | - |
这些题库还在更新中,如果你有不错的面试题库欢迎分享给我,我整理后放上来;人人为我,我为人人,互帮互助,共同提高,祝大家都拿到心仪的Offer!