vue中nextTick,的理解及使用场景

异步更新队列:

首先我们要对vue的数据更新有一定理解: vue是依靠数据驱动视图更新的,该更新的过程是异步的。

即:当侦听到你的数据发生变化时, Vue将开启一个队列(该队列被Vue官方称为异步更新队列)。

视图需要等队列中所有数据变化完成之后,再统一进行更新。示例:

 1 <div >
 2     <input type="button" value="改变文本" @click="change">
 3     <p ref="myP">{{str}}</p>
 4 </div>
 5 <script>
 6     new Vue({
 7         el:"#App",
 8         data:{
 9             str:"我之前很瘦的。"
10         },
11         methods:{
12             change(){
13                 this.str = "现在超胖了!";
14                 // 输出结果:我之前很瘦的。
15                 console.log(this.$refs.myP.innerText)
16             }
17         }
18     })
19 </script>

通过以上示例的输出结果可以有力证明:Vue 实现的响应式并不是数据发生变化之后视图立即变化。


获取更新之后的DOM

Vue官方为了避免开发者直接接触视图,鼓励大家以"数据驱动"的方式进行思考。但,现在的我们想基于更新后的视图来搞点事情,该如何下手?

我们可以使用$nextTick(callback)。这里的回调函数(callback)将在数据更新完成,视图更新完毕之后被调用。

更改上个示例中的change方法如下:

change () {
      this.str = '隐形的翅膀!'
      this.str = '钢铁的翅膀!!'
      this.$nextTick(() => {
          // 输出结果:钢铁的翅膀!!
          console.log(this.$refs.myP.innerText)  
      })
    }

从输出的结果可以看出:我们可以通过$nextTick() 获取到更新之后的DOM

因为 $nextTick() 返回一个 Promise 对象,所以我们也可以使用async/await语法完成相同的事情:

async change () {
    this.str = '隐形的世邦'
    this.str = '肖邦的翅膀'
    await this.$nextTick()
    console.log(this.$ref.myP.innerText)  
 }

或者

change(){
    this.str = "隐形的翅膀";
    this.$nextTick().then(()=>{
        // 输出结果:腾格尔的翅膀
        console.log(this.$refs.myP.innerText);
    });
    this.str = "腾格尔的翅膀"
}

应用场景

1、如果要在created()钩子函数中进行的DOM操作,由于created()钩子函数中还未对DOM进行任何渲染,所以无法直接操作,需要通过$nextTick()来完成。

created () {
    this.$nextTick(()=>{
        this.$refs.myP.innerText = "钢铁的翅膀"
    })
}

注:在created()钩子函数中进行的DOM操作,不使用$nextTick()会报错:

//  Error in created hook: "TypeError: Cannot set property 'innerText' of undefined"
created(){
    this.$refs.myP.innerText = "钢铁的翅膀"
}