Vue使用nextTick的原因和作用

前端精髓

共 1247字,需浏览 3分钟

 ·

2021-12-20 13:26


在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。


疑问:

DOM 更新循环是指什么?

下次更新循环是什么时候?

修改数据之后使用,是加快了数据更新进度吗?

在什么情况下要用到?

原理

Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。


在 Vue 的文档中,说明 Vue 是异步执行 DOM 更新的。


具体来说,异步执行的运行机制如下。


(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。


(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。


(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。


(4)主线程不断重复上面的第三步。


简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。


//改变数据vm.message = 'changed'
//想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新console.log(vm.$el.textContent) // 并不会得到'changed'
//这样可以,nextTick里面的代码会在DOM更新后执行Vue.nextTick(function(){ console.log(vm.$el.textContent) //可以得到'changed'})


第一个 tick(图例中第一个步骤,即'本次更新循环'):

1.首先修改数据,这是同步任务。同一事件循环的所有的同步任务都在主线程上执行,形成一个执行栈,此时还未涉及 DOM 。2.Vue 开启一个异步队列,并缓冲在此事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。


第二个 tick(图例中第二个步骤,即'下次更新循环'):

同步任务执行完毕,开始执行异步 watcher 队列的任务,更新 DOM 。Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel 方法,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。


第三个 tick(图例中第三个步骤):

此时就是文档所说的:下次 DOM 更新循环结束之后。

此时通过 Vue.nextTick 获取到改变后的 DOM 。通过 setTimeout(fn, 0) 也可以同样获取到。


Vue的批量更新原理

浏览 32
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报