Vue.nextTick 的原理和用途

一、问题及原因
Vue.nextTick 的原理和用途
在项目中,我们会发现sopPopups的值在被修改为true后,结果打印出来的sopPopups值还是之前的false,但是在this.$nextTick中打印sopPopups的值为true。这是为什么呢??
原因:
Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新,dom更新是一个异步过程。
具体来说,异步执行的运行机制如下
(1)所有同步任务都在主线程上执行,形成一个执行栈(execution context stack)。
(2)主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
(3)一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列",看看里面有哪些事件。那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行。
(4)主线程不断重复上面的第三步。
所以,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
二、nextTick的原理
结合源码
Vue.nextTick 的原理和用途
nextTick把任务推到一个数组里,在下一个tick去执行这个任务。

1、首先修改数据,this.sopPopups=true和console.log()这是同步任务。同一事件循环的所有的同步任务都在主线程上执行,形成一个执行栈,此时还未涉及 DOM 。
Vue 开启一个异步队列,并缓冲在此事件循环中发生的所有数据改变。如果同一个 watcher 被多次触发,只会被推入到队列中一次。
2、同步任务执行完毕,开始执行异步 watcher 队列的任务,更新 DOM 。Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel 方法,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。
3、DOM 更新循环结束之后,系统就会读取"任务队列",看看里面有哪些事件,此时通过 Vue.nextTick 获取到改变后的 DOM 。通过 setTimeout(fn, 0) 也可以同样获取到。

简单总结事件循环:
同步代码执行 -> 查找异步队列,推入执行栈,执行dom更新,执行Vue.nextTick[事件循环1] ->查找异步队列,推入执行栈,执行dom更新,执行Vue.nextTick[事件循环2]…

二、nextTick的用法
需要在视图更新之后,基于新的视图进行操作。
1、写法,由源码可看出,nextTick有2种写法
(1)
this.sopPopups = true
this. n e x t T i c k ( ( ) = > c o n s o l e . l o g ( t h i s . s o p P o p u p s ) ) ( 2 ) p r o m s i e 写 法 t h i s . s o p P o p u p s = t r u e t h i s . nextTick(() => { console.log(this.sopPopups) }) (2) promsie写法 this.sopPopups = true this. nextTick(()=>console.log(this.sopPopups))(2)promsie写法this.sopPopups=truethis.nextTick().then(() =>{console.log(this.sopPopups)})
2、需要注意的是,在 created 和 mounted 阶段,如果需要操作渲染后的试图,也要使用 nextTick 方法。
****注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.KaTeX parse error: Expected '}', got 'EOF' at end of input: …on () { this.nextTick(function () {

})
}

上一篇:简单理解Vue中的nextTick


下一篇:js执行机制