前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >从vue生命周期中两个“不会保证”说起

从vue生命周期中两个“不会保证”说起

作者头像
mcq
发布2023-03-12 10:49:24
4580
发布2023-03-12 10:49:24
举报

起因

在mounted中使用ref获取一个节点中的子节点,有时会获取不到。

vue2文档-生命周期

文档中说明:

mounted 注意 mounted 不会保证所有的子组件也都被挂载完成。如果你希望等到整个视图都渲染完毕再执行某些操作,可以在 mounted 内部使用 vm.$nextTick

updated 注意,updated 不会保证所有的子组件也都被重新渲染完毕。如果你希望等到整个视图都渲染完毕,可以在 updated 里使用 vm.$nextTick

再次尝试

两个不能保证,没有更多的解释,那我们改用nexttick获取,发现还是还是获取不到。

最后改用setTimeout获取成功

那么,mounted,nexttick,settimeout有什么内在原理呢?

分析

那么,文档说的“不会保证”究竟是哪种情况呢?

如果代码都是同步执行,那就不会出现父组件挂载完成子组件没挂载的情况,所以原因只能是:

异步组件

这里一种例外情况。在你的组件中,包含一个异步组件。因为异步组件一定不会第一时间实例化,自然无法保证子组件节点挂载。

没懂?

再进一步:

因为每个组件有自己的生命周期,所以当虚拟DOM树对比时,根据vue中diff的优化,只会对此组件的虚拟DOM树要更新的部分做更新。 而在某组件虚拟DOM树中,只知道其子组件的构造器(Ctor),传入的数据(data)和子项(children)有没有变化,不关心其子组件内部的虚拟DOM树。 因此,只能保证这个组件要去渲染它的子组件,却无法保证它的子组件内部是如何渲染的。

有点懂了?那有人要问了,既然异步组件无法确定何时才能实例完成,那么使用nextTick进行提取,按理说是可以获取的,然而并没有获取到。但是使用定时器延迟一定时间进行获取却获取到了,这个问题怎么解释?

原理解析

前置知识:宏任务和微任务

当使用nextTick时,将在微任务(不支持微任务的浏览器将回退至宏任务)堆栈中入栈你写的回调。 如果所有子组件都已经下载完毕,并在Vue中定义,则从根组件往后渲染时,因为用的都是同步方法,微任务将在这些同步方法后被执行,所以大多数时候可以通过nextTick获取子组件渲染后的DOM节点。 但是如果实例化组件的时候,有其他微任务入栈,就要看微任务队列的执行顺序了,所以无法完全保证。 对于异步组件,由于网络原因,import微任务总在nextTick之后,所以总是拿不到子组件的DOM。 而在setTimeout一定时间之后,由于setTimeout是宏任务,所以一般会在渲染后执行。 但对于异步组件,如果由于网络延迟,导致微任务在宏任务之后入栈,则在setTimeout的回调中仍无法获取子组件的DOM。 简单的来说,由于有异步执行顺序的影响,只能保证单独组件内部的执行顺序,无法保证其他组件的解析注册执行顺序。

清晰多了吧,再去看vue3文档

vue3文档的生命周期

这里的onMounted和onUpdated中解释多一些,可以看看帮助理解。但也不如我们探讨的深,从官方的解释也印证了我们的思考。

ps:附上小资料 nextTick是微任务还是宏任务?

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-03-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 起因
    • vue2文档-生命周期
      • 再次尝试
        • 分析
          • 再进一步:
            • 原理解析
              • vue3文档的生命周期
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档