【Vue】vue中的$nextTick()
目录一、定义二、实例三、使用nextTick()一、定义vue官方定义:Vue.nextTick([callback,context]),在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新之后的DOM。nextTick是前端面试中vue框架中必考的部分,一定要掌握。它主要是处理我们再变更完数据以后,无法立刻拿到最新的DOM节点对象的问题。我们可以这样理解:vue执行
一、定义
vue官方定义:
Vue.nextTick([callback,context]),在下次DOM更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新之后的DOM。
nextTick是前端面试中vue框架中必考的部分,一定要掌握。它主要是处理我们再变更完数据以后,无法立刻拿到最新的DOM节点对象的问题。我们可以这样理解:vue执行完渲染后会执行this.nextTick()里面的callback函数。
二、实例
对于上面的定义,可能不太好理解,那么举一个小例子:
<div id="app">
<p id="msg">{{message}}</p>
<button @click="change">更新</button>
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods:{
change(){
this.message = 'This is new message!';
console.log('not nextTick():',document.getElementById("msg").innerHTML);
}
}
})
预期结果,vue是响应式的,数据改变会驱动视图改变。所以,应该输出:
not nextTick(): This is new message!
可实际输出却是:
这是为什么呢?页面上视图都更新了,为什么获取到的值还是原来的呢?
Vue在更新DOM的时候,是异步执行的。只要监听到数据变化,vue将开启一个队列,并缓冲在同一事件循环中发生的所有数据变更。如果同一个watcher被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作是非常重要的。然后,在下一个的事件循环“tick”中,Vue 刷新队列并执行实际 (已去重的) 工作。
通俗的说,就是vue data中的数据更新时,它不会立即去渲染页面,也就是修改页面中的dom,而是先存储起来,如果一个数据被改了很多次,以最后一次修改为准,这就是所谓的异步更新DOM。
而我们在改变message之后,直接获取DOM,等于是和数据改变事件同步进行,此时页面上的DOM仍然未更新,获取到的还是原来的“Hello Vue!”旧数据。这也是为什么vue不建议我们直接操作dom的原因之一。
接下来我们使用nextTick解决问题。
三、使用nextTick()
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods:{
change(){
this.message = 'This is new message!';
this.$nextTick(()=>{
console.log('use nextTick():',document.getElementById("msg").innerHTML);
})
console.log('not nextTick():',document.getElementById("msg").innerHTML);
}
}
})
输出:
值得注意的是,即使this.$nextTick写在了console.log('not nextTick():',document.getElementById("msg").innerHTML);前面,但是this.$nextTick中回调函数的输出仍然在后面,这更一步说明了这个输出是异步执行的。
那么,使用setTimeout可以吗?
我们修改js代码:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
},
methods:{
change(){
this.message = 'This is new message!';
setTimeout(()=>{
console.log('use nextTick():',document.getElementById("msg").innerHTML);
})
console.log('not nextTick():',document.getElementById("msg").innerHTML);
}
}
})
结果:
可以看到,和使用nextTick效果是一样的,因为setTimeout中的回调函数也是在本次执行栈清空后被调用的,可以参考:
深入学习JS:任务队列和事件循环
js中各异步调用的执行顺序:
同步代码 > nextTick > Promise> setTimeout
由于
vue是在下一个的事件循环“tick”中,刷新队列并执行实际 (已去重的) 工作。
所以setTimeout中输出函数获取到的值肯定是更新以后的值。
所以总结一下,使用this.$nextTick()之所以能获取到更新后的值,并不是改变了vue的渲染流程,而是改变了获取最新值的时间,并不是立即获取,而是等vue渲染完后再获取,即异步获取。
更多推荐






所有评论(0)