资讯专栏INFORMATION COLUMN

[vuejs 踩坑实战系列] 路由场景下父子组件的生命周期顺序来个刨根问底

FreeZinG / 2881人阅读

摘要:大家中秋假期快乐,假期分享一些原理设计文章给大家原创不易,欢迎转发,一起学习凌晨写的,不容易哈,收藏或者点个赞吧在常见的单页应用中,我们都会有一个根文件,里面放置一个然后配置路由来切换很多人在子父组件嵌套关系下的生命周期钩子函数如何应用,

大家中秋假期快乐,假期分享一些原理设计文章给大家

原创不易,欢迎转发,一起学习(凌晨写的,不容易哈,收藏或者点个赞吧)

在常见的单页应用中,我们都会有一个根 App.vue 文件,里面放置一个 router-view 然后配置路由来切换.

很多人在子父组件嵌套关系下的生命周期钩子函数如何应用,谁先谁后(比如哪个用来发送请求,数据传递)等有所疑问。

本文聚焦 mounted 事件(需要 created 的可以留言哈),先抛结论:

子组件一层一层往外触发,最终触发根 App.vue 的 mounted

验证的做法很简单:

你只需要在每一个组件里面的 mounted 增加打印日志就可以看到了,我们具体来看看设计原理

现在假设我们配置了路由:

一级是 /user/:id 二级是 profile

const router = new VueRouter({
  routes: [
    { 
      path: "/user/:id", 
      component: User,
      children: [
        {
          // 当 /user/:id/profile 匹配成功,
          // UserProfile 会被渲染在 User 的  中
          path: "profile",
          component: UserProfile
        }
      ]
    }
  ]
})

先看一下所有的 mounted 最终在各自组件里面是如何被调用的:

通过 vm.$options 获取组件内部的配置,然后通过 call 方法

下面的我们又会遇到 vnode(所以掌握它很重要,在前面的 vue.js 源码原创系列 ref 与 $refs 如何关联 也提到了一些 vnode,感兴趣可以看看),就是下面 componentVNodeHooks 里面的 insert 函数的参数

var componentVNodeHooks = {
  insert: function insert (vnode) {}
}

里面呢,第一步:从 vnode 里面获取 componentInstance

var componentInstance = vnode.componentInstance;

然后判断 _isMounted 是否已经执行过 mounted (很常用的状态二次确定的变量,前面的 _ 一般代表内部使用)

if (!componentInstance._isMounted) {
  componentInstance._isMounted = true;
  callHook(componentInstance, "mounted");
}

上面我们就用到了 callHook 函数了,传入的第二个参数也正是本文讨论的生命周期的 mounted

再往后有一个 invokeInsertHook 函数

function invokeInsertHook (vnode, queue, initial) {
}

注意一下源码里面的注释:

delay insert hooks for component root nodes, invoke them after the element is really inserted

设置了 pendingInsert(后面会在 initComponent 中使用),代码如下:

if (isTrue(initial) && isDef(vnode.parent)) {
  vnode.parent.data.pendingInsert = queue;
}

内部设计:循环 queue 这个包含 vnode 的数组对象,如图所示:

注意一下标注的 data.hook,下面的代码片段会使用到,也就是调用上面提到的 componentVNodeHooks 对象的 insert

for (var i = 0; i < queue.length; ++i) {
  queue[i].data.hook.insert(queue[i]);
}

再往下,带着疑问:

这个 queue 是如何生成 vnode 数组的呢?

最开始定义一个空数组:

var insertedVnodeQueue = [];

在刚才的 对象中还有 init

var componentVNodeHooks = {
  init: function init () {
    // ...
  }
}

init 函数内部定义一个 child

var child = vnode.componentInstance = createComponentInstanceForVnode(...)

然后会调用一个 $mount

child.$mount(hydrating ? vnode.elm : undefined, hydrating);

在函数 initComponent 中会用到之前的 pendingInsert,而且 insertedVnodeQueue 这个数组对象会调用 push 插入元素

function initComponent (vnode, insertedVnodeQueue) {
  if (isDef(vnode.data.pendingInsert)) {
    insertedVnodeQueue.push.apply(insertedVnodeQueue, vnode.data.pendingInsert);
    vnode.data.pendingInsert = null;
  }
}

在函数 invokeCreateHooks 内部insertedVnodeQueue 这个数组对象会调用 push 插入元素

function invokeCreateHooks (vnode, insertedVnodeQueue) {
  i = vnode.data.hook; // Reuse variable
  if (isDef(i)) {
    if (isDef(i.insert)) { 
      insertedVnodeQueue.push(vnode); 
    }
  }
}

在函数 mountComponent 内部当 vm.$vnode 为 null 也会调用 callHook,第二个参数传入 mounted

function mountComponent () {
  if (vm.$vnode == null) {
    vm._isMounted = true;
    callHook(vm, "mounted");
  }
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/108542.html

相关文章

  • [vuejs 踩坑实战系列] keep-alive 被 beforeRouteEnter 骗了

    摘要:大家中秋假期快乐,假期分享一些实战文章给大家,原创不易,欢迎转发,一起学习现在大家基本都在单页应用里面使用了来缓存不活动的组件实例,而不是销毁它们。 大家中秋假期快乐,假期分享一些实战文章给大家,原创不易,欢迎转发,一起学习 现在大家基本都在单页应用里面使用了 keep-alive 来缓存不活动的组件实例,而不是销毁它们。 如果你还没有使用,可以看看官方的介绍(如果大家需要一些新手入...

    MrZONT 评论0 收藏0
  • 关于Vue2一些值得推荐文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    sutaking 评论0 收藏0
  • 关于Vue2一些值得推荐文章 -- 五、六月份

    摘要:五六月份推荐集合查看最新的请点击集前端最近很火的框架资源定时更新,欢迎一下。苏幕遮燎沈香宋周邦彦燎沈香,消溽暑。鸟雀呼晴,侵晓窥檐语。叶上初阳乾宿雨,水面清圆,一一风荷举。家住吴门,久作长安旅。五月渔郎相忆否。小楫轻舟,梦入芙蓉浦。 五、六月份推荐集合 查看github最新的Vue weekly;请::点击::集web前端最近很火的vue2框架资源;定时更新,欢迎 Star 一下。 苏...

    khs1994 评论0 收藏0
  • Vue.js学习

    摘要:一基础学习模式下图不仅概括了模式,还描述了在中是如何和以及进行交互的。关于这一点我们将在后续反应系统中讨论。父组件通过向下传递数据给子组件,子组件通过给父组件发送消息。这个对象必须是普通对象原生对象,及原型属性会被忽略。 Vue.js 是用于构建交互式的 Web 界面的库。Vue.js 提供了 MVVM 数据绑定和一个可组合的组件系统,具有简单、灵活的 API。 其实和Jquery一样...

    TIGERB 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<