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

原理:
异步说明
Vue实现响应式并不是数据发生变化之后DOM立即改变,而是按照一定的策略进行DOM的更新。
在Vue的文档中,说明Vue是异步更新DOM的

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

  1. 所有同步任务都在主线程上执行,形成一个执行栈。
  2. 主线程之外还存在一个任务队列(task quene),只要异步任务有了运行结果,就在任务队列之中放置一个事件。
  3. 一旦”执行栈”中的所有同步任务执行完毕,系统就会读取”任务队列”看看里面有哪些事件,那些对应的异步任务,于是结束等待状态,进入执行栈,开始执行
  4. 主线程不断重复上面的第三步

WechatIMG19.png

事件循环

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

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

应用场景

需要在视图更新以后,基于新的视图进行操作
created,mounted
需要注意的是,在created和mounted阶段,如果需要操作渲染过后的视图,也要使用nextTick方法

官方文档说明:
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted

  1. mounted: function () {
  2. this.$nextTick(function () {
  3. // Code that will run only after the
  4. // entire view has been rendered
  5. })
  6. }

例子1:
点击按钮显示原本以 v-show = false 隐藏起来的输入框,并获取焦点

  1. showsou(){
  2. this.showit = true //修改 v-show
  3. document.getElementById("keywords").focus() //在第一个 tick 里,获取不到输入框,自然也获取不到焦点
  4. }

修改为

  1. showsou(){
  2. this.showit = true
  3. this.$nextTick(function () {
  4. // DOM 更新了
  5. document.getElementById("keywords").focus()
  6. })
  7. }

例子2:
点击获取元素宽度。

  1. <div id="app">
  2. <p ref="myWidth" v-if="showMe">{{ message }}</p>
  3. <button @click="getMyWidth">获取p元素宽度</button>
  4. </div>
  5. getMyWidth() {
  6. this.showMe = true;
  7. //this.message = this.$refs.myWidth.offsetWidth;
  8. //报错 TypeError: this.$refs.myWidth is undefined
  9. this.$nextTick(()=>{
  10. //dom元素更新后执行,此时能拿到p元素的属性
  11. this.message = this.$refs.myWidth.offsetWidth;
  12. })
  13. }

slo