nextTick相当于一个异步函数:在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
Vue中DOM渲染是在mounted()钩子函数中,created()钩子函数中DOM还未渲染,无法直接操作DOM
1、在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
在created()钩子函数执行的时候DOM 其实并未进行任何渲染,而此时进行DOM操作无异于徒劳,所以此处一定要将DOM操作的js代码放进Vue.nextTick()的回调函数中。与之对应的就是mounted()钩子函数,因为该钩子函数执行时所有的DOM挂载和渲染都已完成,此时在该钩子函数中进行任何DOM操作都不会有问题 。
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index">{{item}}</li>
</ul>
</div>
<script>
let app = new Vue({
data: {
arr: [1,2,3],
},
created() {
console.log('created',document.querySelectorAll('li').length)
this.$nextTick(()=>{
console.log('nextTick',document.querySelectorAll('li').length)
document.querySelectorAll('li')[0].innerHTML="created中更改了按钮内容";
})
}
});
</script>
2、当项目中你想在改变DOM元素的数据后基于新的dom做点什么,对新DOM一系列的js操作都需要放进Vue.nextTick()的回调函数中;通俗的理解是:更改数据后当你想立即使用js操作新的视图的时候需要使用它
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index" @click="getAdd">{{item}}</li>
</ul>
</div>
<script>
let app = new Vue({
data: {
arr: [1,2,3],
},
methods: {
getAdd(){
this.arr = [4,5,6,7];
this.$nextTick(()=>{
document.querySelectorAll('li')[3].innerHTML="33333333333333";
console.log('nextTick',document.querySelectorAll('li').length)
})
},
},
created() {
console.log('created',document.querySelectorAll('li').length)
}
});
</script>
li点击后 页面展示 由上图更改为
如果不放在nextTick中
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index" @click="getAdd">{{item}}</li>
</ul>
</div>
<script>
let app = new Vue({
data: {
arr: [1,2,3],
},
methods: {
getAdd(){
this.arr = [4,5,6,7];
document.querySelectorAll('li')[3].innerHTML="44444444444444";
console.log('methods',document.querySelectorAll('li').length)
},
},
created() {
console.log('created',document.querySelectorAll('li').length)
}
});
</script>
<div id="app">
<ul>
<li v-for="(item,index) in arr" :key="index" @click="getAdd">{{item}}</li>
</ul>
</div>
<script>
let app = new Vue({
data: {
arr: [1,2,3],
},
methods: {
getAdd(){
this.arr = [4,5,6,7];
setTimeout(() => {
document.querySelectorAll('li')[3].innerHTML="44444444444444";
console.log('methods', document.querySelectorAll('li').length);
});
},
},
created() {
console.log('created',document.querySelectorAll('li').length)
}
});
</script>
nextTick与setTimeout都是异步函数 不同的是nextTick比setTimeout优先执行
原因:
macro-task(宏任务):包括整体代码script,setTimeout,setInterval
micro-task(微任务):Promise,process.nextTick
process.nextTick:process.nextTick(callback)类似node.js版的"setTimeout",在事件循环的下一次循环中调用 callback 回调函数。
javascript是单线程
setTimeout:因为要入微任务队列,即使是0最快也要4ms,要等待出队。
宏任务的执行时间大于微任务的执行时间