持续创作,加速成长!这是我参与「掘金日新计划 · 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->d
created () { 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
。