nextTick
Vue更新DOM是异步的,数据更新是同步的。
nextTick下一帧去读取DOM更新之后的信息。
nextTick的用法
-
传一个回调函数
语法:
nextTick(() => { // 操作DOM元素 }) -
配合async/await使用
语法:
const setDomProperties = async () => { await nextTick() // 操作DOM元素,在await下面的代码全是异步的 }
假设我们有一个元素一开始是用v-if隐藏的,v-if是直接操作DOM的,为false的话直接从DOM中删除元素,为true在DOM中添加元素。我们用一个flag变量去切换section元素的显示隐藏。并获取section去改变它里面的内容:
没有使用nextTick时:
<template>
<div>
<article>
<section ref="section" v-if="flag"></section>
</article>
<button @click="getDom">获取DOM</button>
</div>
</template>
<script setup lang='ts'>
import { ref } from 'vue'
// 控制section元素显示隐藏
const flag = ref(false)
// ref获取section DOM元素
const section = ref()
// 显示section并更改它里面文字的内容
const getDom = () => {
flag.value = true
console.log(section.value); // undefined
section.value.innerText = '酱酱' // 报错
}
</script>
<style lang='scss' scoped></style>
结果:
可以看到打印section.value为undefined, 并且更改它的内容直接报错。
这说明压根就没有获取到section元素对象。
使用nextTick后:
<template>
<div>
<article>
<section ref="section" v-if="flag"></section>
</article>
<button @click="getDom">获取DOM</button>
</div>
</template>
<script setup lang='ts'>
import { ref, nextTick } from 'vue'
// 控制section元素显示隐藏
const flag = ref(false)
// ref获取section DOM元素
const section = ref()
// 显示section并更改它里面文字的内容
const getDom = () => {
flag.value = true
nextTick(() => {
console.log(section.value);
section.value.innerText = '酱酱'
})
}
</script>
<style lang='scss' scoped></style>
结果:
当我们操作DOM的时候,发现数据取的是更新前的,或者是获取不到DOM的时候,就可以尝试用nextTick去解决。
nextTick实际上就是把传的回调函数中的代码,放到Promise里面去执行,大家都知道Prmoise是一个异步任务(微任务),Vue更新DOM是异步的,nextTick就是在DOM更新后去执行的函数。