Vue中异步更新队列

Vue 在更新 DOM 时是异步执行的

看下官网介绍:

只要侦听到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。Vue 在内部对异步队列尝试使用原生的 Promise.then、MutationObserver 和 setImmediate,如果执行环境不支持,则会采用 setTimeout(fn, 0) 代替。

重点:
1.数据变化开启一个异步队列

2.同一个watcher多次触发只会推入到队列一次,解决重复操作问题

3.在下一个tick中,vue刷新队列并执行实际 (已去重的) 工作

先来看一个例子:一个div,有v-if控制是否渲染,点击按钮对div的显示/隐藏做改变,并在显示时,获取里边的文本 。
在这里插入图片描述
按照平时思路:

当v-if="true"时,div被渲染出来,document.getElementById(“div”).innerHTML可以获取里面的文本。

实际情况:

代码运行后,控制台会抛出一个错误,意思是获取不到div元素。这里就涉及到Vue的一个重要概念:异步更新队列。
在这里插入图片描述
[去重机制]

Vue这种去重机制减少了开销,如果一个for循环来动态改变数据100次,其实它只会应用最后一次改变,如果没有这种机制,DOM就要重绘 100 次。

[异步更新队列实现的选择]

Vue会根据当前浏览器环境优先使用原生的Promise.then 和MutationObserve。
如果都不支持就会采用setTimeout代替。

[代码报错原因]

在执行this.showDiv = "true"时,div并没有被创建出来,直到下一个Vue事件循环时,才开始创建。

Vue提供了$ nextTick来告知DOM声明时候完成更新,我们可以在$nextTick中进行div内容的获取,修改上面的例子。
在这里插入图片描述
通过修改后首次点击不会报错

再看一个例子:
在这里插入图片描述
在这里插入图片描述
视图上每一次响应党的是最后一次数据的改变,而不是从0-100一个一个变化。

这个例子更好的体验了Vue中异步更新队列的去重机制。

$nextTick的用途

应用场景: 在视图更新之后,基于新的视图进行操作。

看一个例子: 点击show按钮使得 原来v-if="false"的input框显示,并且获得焦点
在这里插入图片描述
下面再具体看下$nextTick方法的使用!

$nextTick多用于vue中的DOM数据异步更新!

下面了解下nextTick的主要应用的场景及原因:

1、在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。

因为在created()钩子函数执行的时候 DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。

2、在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。

(源码就不看了吧!!)

再回顾一下生命周期:

在这里插入图片描述

beforeCreate( 创建前 )
在实例初始化之后,数据观测和事件配置之前被调用,此时组件的选项对象还未创建,el 和 data 并未初始化,因此无法访问methods, data, computed等上的方法和数据。

created ( 创建后 )
实例已经创建完成之后被调用,在这一步,实例已完成以下配置:数据观测、属性和方法的运算,watch/event事件回调,完成了data 数据的初始化,el没有。 然而,挂在阶段还没有开始, $el属性目前不可见,这是一个常用的生命周期,因为你可以调用methods中的方法,改变data中的数据,并且修改可以通过vue的响应式绑定体现在页面上,,获取computed中的计算属性等等,通常我们可以在这里对实例进行预处理,也有一些童鞋喜欢在这里发ajax请求,值得注意的是,这个周期中是没有什么方法来对实例化过程进行拦截的,因此假如有某些数据必须获取才允许进入页面的话,并不适合在这个方法发请求,建议在组件路由钩子beforeRouteEnter中完成

beforeMount(挂载前)
挂在开始之前被调用,相关的render函数首次被调用(虚拟DOM),实例已完成以下的配置: 编译模板,把data里面的数据和模板生成html,完成了el和data 初始化,注意此时还没有挂在html到页面上。

mounted(挂载后)
挂在完成,也就是模板中的HTML渲染到HTML页面中,此时一般可以做一些ajax操作,mounted只会执行一次。

beforeUpdate(更新前)
在数据更新之前被调用,发生在虚拟DOM重新渲染和打补丁之前,可以在该钩子中进一步地更改状态,不会触发附加地重渲染过程

updated(更新后)
在由于数据更改导致地虚拟DOM重新渲染和打补丁只会调用,调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作,然后在大多是情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环,该钩子在服务器端渲染期间不被调用

beforeDestroy(销毁前)
在实例销毁之前调用,实例仍然完全可用,

这一步还可以用this来获取实例,
一般在这一步做一些重置的操作,比如清除掉组件中的定时器 和 监听的dom事件
destroyed(销毁后)
在实例销毁之后调用,调用后,所以的事件监听器会被移出,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用

再看一下属性:

vm.$el
获取Vue实例关联的DOM元素;

vm.$data
获取Vue实例的data选项(对象)

vm. o p t i o n s 获 取 V u e 实 例 的 自 定 义 属 性 ( 如 v m . options 获取Vue实例的自定义属性(如vm. optionsVuevm.options.methods,获取Vue实例的自定义属性methods)

vm. r e f s 获 取 页 面 中 所 有 含 有 r e f 属 性 的 D O M 元 素 ( 如 v m . refs 获取页面中所有含有ref属性的DOM元素(如vm. refsrefDOMvm.refs.hello,获取页面中含有属性ref = “hello”的DOM元素,如果有多个元素,那么只返回最后一个)

参考:https://blog.csdn.net/qq_41257129/article/details/95175638

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值