持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第3天,点击查看活动详情
theme: channing-cyan
前言
在写项目的时候,会遇到更新了DOM,但是获取到的是为更新前的数据,此时就需要用放到Vue提供的nextTick,本篇文章聊一聊nextTick,但是在讲nextTick之前,需要先了解一下JS的执行机制
介绍
-
js执行机制JavaScript是单线程执行的,将需要执行的任务,分为同步任务和异步任务- 同步任务:
JS会将同步任务放入主线程,形成一个栈,并且是依次执行 - 异步任务:不进入主线程,并且异步任务可以分为宏任务与微任务
- 宏任务:主代码块、
setTimeout、setInterval、setImmedia - 微任务:
process.nextTick()、Promise.then、catch
- 宏任务:主代码块、
浏览器在执行
JS代码时,是按照:同步、异步(微任务、宏任务、微任务...)的顺序依次执行 - 同步任务:
-
nextTick将传入的函数,变成异步任务,如果通过
nextTick包裹的方法获取DOM,获取到的是更新后的DOM示例
created () { console.log('a'); console.log('c') }, mounted () { console.log('b') console.log('d') }执行顺序:
a->c->b->dcreated () { console.log('a'); this.$nextTick(() => { console.log('c') }) }, mounted () { console.log('b') this.$nextTick(() => { console.log('d') }) }执行顺序:
a->b->c->d可以看出,添加了
nextTick,会将同步任务转为异步任务,从而延迟了执行时间 -
nextTick和setTimeout的比较之前我将事件转为异步任务使用的是
setTimeout,那么nextTick和setTimeout有什么区别吗?nextTick源码中利用的是Promise.resolve()实现的,所以,区别在于setTimeout是宏任务,nextTick是微任务,上面我们已经说过,JS的执行顺序是同步、异步(微任务、宏任务、微任务...),所以nextTick的执行顺序优先于setTimeout,当然setTimeout也可以替代nextTick
使用场景
当我们修改DOM,并且获取DOM内容时,如果直接获取,那么获取到的时未更新的DOM,此时就需要用到$nextTick,实现异步获取
代码:
<template>
<div>
<h1 ref="name">{{name}}</h1>
<button @click="btn">点击获取name</button>
</div>
</template>
<script>
export default {
data () {
return {
name: '张三'
}
},
methods: {
btn () {
this.name = '李四';
console.log('直接获取修改后的DOM' + this.$refs.name.innerHTML);
this.$nextTick(() => {
console.log('通过nextTick异步获取修改后的DOM' + this.$refs.name.innerHTML);
})
}
},
}
</script>
-
点击按钮,显示元素,并获取元素的高度
<template> <div> <div type="text" ref="name" v-if="isShow">box</div> <button @click="btn">点击获取高度</button> </div> </template> <script> export default { data () { return { isShow: false } }, methods: { btn () { this.isShow = true console.log(this.$refs.name.offsetHeight); this.$nextTick(() => { console.log(this.$refs.name.offsetHeight); }) } }, } </script>
如果没有添加nextTick,获取元素属性会报错,因为,此时DOM还没更新,this.$refs.name还不存在,所以会报错。如果添加nextTick,会异步执行,先操作DOM,后执行回调。
总结
当我们操作DOM,并且需要获取到的是,DOM改变后的数据时,就需要使用nextTick。