官方文档说明:
用法:
在下次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-showdocument.getElementById("keywords").focus() //在第一个 tick 里,获取不到输入框,自然也获取不到焦点}
修改为
showsou(){this.showit = truethis.$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 undefinedthis.$nextTick(()=>{//dom元素更新后执行,此时能拿到p元素的属性this.message = this.$refs.myWidth.offsetWidth;})}
slo
