首先我们来了解一下$nextTick()用法原理:
在vue中更新DOM是异步操作,$nextTick()的主要应用场景和原因:
在vue生命周期的created()钩子函数进行DOM操作一定要放在vue.nextTick()的回调函数中;
--在created()钩子函数执行的时候DOM 其实还并未进行渲染,所以这个时候进行DOM操作也没用,数据不会有任何改变,
所以想要在created里操作,就要把数据放在vue.nextTick()中;
··与之对应的是mounted()钩子函数,因为该函数执行时所有DOM挂载和渲染都已经完成,
此时DOM操作在该钩子函数中进行不会有问题。
--如果你想修改某数据,并及时得到更新后的DOM结构,可以使用vue.nextTick()
为什么要使用$nextTick():|举例理解
<div ref="onediv">{{ onediv }}</div> 第一个div
<div>{{ twodiv }}</div> 第二个div
<button @click="handleClick">点击我将000改成456</button>
data() {
return {
onediv: "123",
twodiv: "000"
};
}
methods: {
// 当我点击按钮的时候,将第一个div的值123改变成456,同时获取到div改变后的值456,赋给第二个div。
// 也就是说结果两个div都应该为456.
handleClick() {
this.onediv = "456";
this.twodiv = this.$refs.onediv.innerHTML;// 通过原生$ref获取到第一个div改变后的值,然后赋给第二给div
console.log(this.twodiv);
}
}
我们发现,第一个div确实是改变了,但是第二个div获取到的值却是第一个div之前的值,这时候想获取页面最新的DOM节点,却发现获取到的是旧值,因为Dom还没有更新循环完,这是因为onediv数据在发现变化的时候,vue并不会立马去更新DOM,而是将修改数据的操作放进了一个异步操作队列中所以它的值还是123
所以我们用$nextTick()来操作他,得到我们想要的值
methods: {
handleClick() {
this.onediv = "456";
this.$nextTick(() => {
this.twodiv = this.$refs.onediv.innerHTML;
console.log(this.twodiv);
});
}
}
刚才的案例,同时也说明了一个问题,Vue 在更新 DOM 时是异步执行的。所以this.$nextTick是处理异步的一个回调函数,它返回的是一个promise对象,那么我们这个代码也可以用promise来改写,我们可以用 ES7 async/await 语法完成相同的事情:
methods: {
async handleClick() {
this.onediv = "456";
await this.$nextTick(); // await 等待返回值后,再执行下面的事情。
this.twodiv = this.$refs.onediv.innerHTML;
console.log(this.twodiv);
}
}
//结果是一样的
实现原理:
首先,先了解nextTick()中定义的三个重要变量:
- callbacks
用来存储所有需要执行的回调函数
- penging
用来标志是否正在执行回调函数
- timerFunc
用来触发执行回调函数
后续更新。。。