官方文档说明:
用法:
在下次DOM更新循环结束之后执行延迟回调,在修改数据之后立即使用这个方法,获取更新后的DOM
原理:
异步说明
Vue实现响应式并不是数据发生变化之后DOM立即改变,而是按照一定的策略进行DOM的更新。
在Vue的文档中,说明Vue是异步更新DOM的
具体来说,异步执行的运行机制如下:
- 所有同步任务都在主线程上执行,形成一个执行栈。
- 主线程之外还存在一个任务队列(task quene),只要异步任务有了运行结果,就在任务队列之中放置一个事件。
- 一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”看看里面有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
- 主线程不断重复上面的第三步
事件循环
简单来说,vue在修改数据之后,视图不会立即更新,而是等同一事件循环中的所有数据变化之后,再统一进行视图更新,
//改变数据
vm.message = ‘changed’
//想要立即使用更新后的DOM。这样不行,因为设置message后DOM还没有更新
console.log(vm.$el.textContent) // 并不会得到’changed’
//这样可以,nextTick里面的代码会在DOM更新后执行
Vue.nextTick(function(){
console.log(vm.$el.textContent) //可以得到’changed’
})
应用场景
需要在视图更新以后,基于新的视图进行操作
created,mounted
需要注意的是,在created和mounted阶段,如果需要操作渲染过后的视图,也要使用nextTick方法
官方文档说明:
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
例子1:
点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点
showsou(){
this.showit = true //修改 v-show
document.getElementById("keywords").focus() //在第一个 tick 里,获取不到输入框,自然也获取不到焦点
}
修改为
showsou(){
this.showit = true
this.$nextTick(function () {
// DOM 更新了
document.getElementById("keywords").focus()
})
}
例子2:
点击获取元素宽度。
<div id="app">
<p ref="myWidth" v-if="showMe">{{ message }}</p>
<button @click="getMyWidth">获取p元素宽度</button>
</div>
getMyWidth() {
this.showMe = true;
//this.message = this.$refs.myWidth.offsetWidth;
//报错 TypeError: this.$refs.myWidth is undefined
this.$nextTick(()=>{
//dom元素更新后执行,此时能拿到p元素的属性
this.message = this.$refs.myWidth.offsetWidth;
})
}
slo