阿西河

所有教程

公众号
🌙
阿西河前端的公众号

我的收藏

    最近访问  (文章)

      教程列表

      抓包专区
      测试专区

      Vue.js 父子组件生命周期调用顺序

      问题

      Vue父子组件生命周期调用顺序

      过程理解

      加载渲染过程

      父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

      子组件更新过程

      父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

      父组件更新过程

      父beforeUpdate -> 父updated

      销毁过程

      父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

      答案

      组件的调用顺序都是先父后子,渲染完成的顺序肯定是先子后父

      组件的销毁操作是先父后子,销毁完成的顺序是先子后父

      https://a.axihe.com/focus/vue/23.jpg

      对应源码

      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前端面试题 ,这里基本包涵了市场上的所有前端方面的面试题,也有一些大公司的面试图,可以让你面试更加顺利。

      面试题
      HTMLCSSJavaScript
      jQueryVue.jsReact
      算法HTTPBabel
      BootStrapElectronGulp
      Node.js前端经验相关前端综合
      Webpack微信小程序-

      这些题库还在更新中,如果你有不错的面试题库欢迎分享给我,我整理后放上来;人人为我,我为人人,互帮互助,共同提高,祝大家都拿到心仪的Offer!

      目录
      目录