初识vue 2.0(12):使用$nextTick获取更新后的DOM

Posted phptree

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了初识vue 2.0(12):使用$nextTick获取更新后的DOM相关的知识,希望对你有一定的参考价值。

Vue 异步执行 DOM 更新。

只要观察到数据变化,Vue 将开启一个队列,并缓冲在同一事件循环中发生的所有数据改变。

如果同一个 watcher 被多次触发,只会被推入到队列中一次。这种在缓冲时去除重复数据对于避免不必要的计算和 DOM 操作上非常重要。

然后,在下一个的事件循环"tick"中,Vue 刷新队列并执行实际 (已去重的) 工作。

Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。

 

例如,当你设置 vm.msg = ‘Hello world‘ ,该组件不会立即重新渲染。当刷新队列时,组件会在事件循环队列清空时的下一个"tick"更新。

多数情况我们不需要关心这个过程,但是如果你想在 DOM 状态更新后做点什么,这就可能会有些棘手。

虽然 Vue.js 通常鼓励开发人员沿着"数据驱动"的方式思考,避免直接接触 DOM,但是有时我们确实要这么做。

为了在数据变化之后等待 Vue 完成更新 DOM ,可以在数据变化之后立即使用 Vue.nextTick(callback) 。

这样回调函数在 DOM 更新完成后就会调用。

 

使用场景:

1. 在Vue生命周期的 created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中。

2. 在数据变化后要执行的某个操作,例如数据变化后立刻操作DOM。

例子:

创建Hello.vue组件,注意标注中的执行顺序

<template>
    <div class="hello">
        <span @click="update" ref="msg">{{ msg }}</span>
        <router-link to="Game">Game</router-link>
    </div>
</template>
<script>
export default {
    name: Hello,
    data () {
        return {
            msg:"Hello"//原始数据
        }
    },
    methods: {
        update(e){
            this.msg = Hello world;//更改数据
            
            console.log(Start: + e.target.innerText);//1 Hello
            
            this.$nextTick(function(){
                console.log(nextTick: + e.target.innerText);//5 Hello world
            });
            
            setTimeout(function(){
                console.log(setTimeout: + e.target.innerText);//6 Hello world
            },0);  
            
            console.log(End: + this.$refs.msg.innerText);//2 Hello
        }
    },
    beforeUpdate(){
        console.log(beforeUpdate: + this.$refs.msg.innerText);//3 Hello
    },
    updated(){
        console.log(updated: + this.$refs.msg.innerText);//4 Hello world
    },
    created(){
        //直接输出会报错
        this.$nextTick(function(){
            console.log(created: + this.$refs.msg.innerText);//2 Hello
        });
    },
    mounted(){
        console.log(mounted: + this.$refs.msg.innerText);//1 Hello
    },
}
</script>

<style>
.hello{
  background-color:#E1FFFF;
}
</style>

例子中,仿佛setTimeout(fn, 0)和Vue.nextTick()是一样的效果?

官网解释:

Vue 在内部尝试对异步队列使用原生的 Promise.then 和 MessageChannel,如果执行环境不支持,会采用 setTimeout(fn, 0) 代替。

例子中,仿佛可以使用mounted或者updated代替Vue.nextTick()?

官网解释:

使用 mounted 并不能保证钩子函数中的 this.$el 在 document 中。为此还应该引入 Vue.nextTick/vm.$nextTick。例如:

mounted() {
  this.$nextTick(function () {
    // 代码保证 this.$el 在 document 中
  })
}

参考:

https://cn.vuejs.org/v2/api/#Vue-nextTick

https://cn.vuejs.org/v2/guide/migration.html#ready-%E6%9B%BF%E6%8D%A2

https://cn.vuejs.org/v2/guide/reactivity.html#%E5%BC%82%E6%AD%A5%E6%9B%B4%E6%96%B0%E9%98%9F%E5%88%97

 

以上是关于初识vue 2.0(12):使用$nextTick获取更新后的DOM的主要内容,如果未能解决你的问题,请参考以下文章

初识vue 2.0:路由与组件

初识vue 2.0:vuex进阶

初识vue 2.0(13):子组件使用watch监听父组件变化

初识vue 2.0:vuex组件通信

在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有啥区别

Vue:传递给 vm.$nextTick 的函数何时执行?