首页 > 其他分享 >从vue生命周期中两个“不会保证”说起

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

时间:2023-03-11 14:45:08浏览次数:48  
标签:nextTick 异步 生命周期 DOM 说起 获取 任务 vue 组件

起因

在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是微任务还是宏任务?

标签:nextTick,异步,生命周期,DOM,说起,获取,任务,vue,组件
From: https://www.cnblogs.com/macq/p/17205969.html

相关文章

  • vue2使用ECharts自适应大小
    1.安装监听容器大小变化的插件npminstallelement-resize-detector--save2.ECharts已经有重新绘制图表的函数 resize();<template><divid="home">......
  • Java基础之并发——线程的生命周期和状态
    Java线程在运行的生命周期中的指定时刻只可能处于下面6种不同状态的其中一个状态:NEW:初始状态,线程被创建出来但没有被调用start()。RUNNABLE:运行状态,线程被调用......
  • VUE+.NET应用系统的国际化-多语言词条服务
    上篇文章我们介绍了VUE+.NET应用系统的国际化-整体设计思路系统国际化改造整体设计思路如下:提供一个工具,识别前后端代码中的中文,形成多语言词条,按语言、界面、模块统一......
  • vue中执行异步函数async和await的用法
    在开发中,可能会遇到两个或多个函数异步执行的情况,对于Vue中函数的异步函数执行做了一个小总结,如下:异步执行使用async和await完成created(){this.init()},meth......
  • Vue实现div可拖动组件 并可操纵盒子大小
    Vue实现div可拖动组件并可操纵盒子大小借鉴文章:https://blog.csdn.net/qq_46103732/article/details/128902192场景:在pc端项目中会碰到弹框后多个页面重叠的场景,类似......
  • vue3请求编写规范
    vue3请求编写规范使用的是模块化的组件式API界面request(请求文件夹)总文件夹中包含了对应的接口文件xxxx.ts包含了管理最底层请求的request.ts包含了......
  • vue動態產生div及v-model數據綁定
    html模板遍歷會涉及到v-model對值的綁定,這里的思路是根據數組中的下標尋找對應行數據<divclass="row"v-for="item,indexinitems"><divclass="col-3">......
  • vue+leaflet示例:地图分屏对比展示(附源码下载)
    demo源码运行环境以及配置运行环境:依赖Node安装环境,demo本地Node版本:14.19.1。运行工具:vscode或者其他工具。配置方式:下载demo源码,vscode打开,然后顺序执行以下命令:(1)......
  • Vue————Vue v2.7.14 入口文件【二】
    前言按着我的习惯,拿到一个项目首先我会查看项目下的README.md其次查看package.json,这里也不例外看过README.md后,来看下package.json;GitHubgithubpage内容package.......
  • Vue——Vue v2.7.14 源码阅读之代码目录结构【一】
    前言这里主要说一些vue2.7.14源码的目录结构,其实这块有些目录并不重要,不过我还是想全面的描述下,详细的一些文件说明会随着源码解读来补充完善,其中描述如果有错的地方还......