由于性能优化的需要,处在调用栈中的同步任务会先于模板更新执行,因此下面的这段代码输出的还是'我是小满'
<template>
<div ref="div">{{ message }}</div>
<button @click="change">改变值</button>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted,nextTick } from 'vue'
let message = ref<string>('我是小满')
let div = ref<HTMLElement>()
const change = async () => {
message.value = '小满最骚'
console.log(div.value?.innerHTML) // 仍然打印'我是小满'
}
</script>
<style scoped></style>
如果需要输出'小满最骚',可以在console.log语句之前加入一句await nextTick()
<template>
<div ref="div">{{ message }}</div>
<button @click="change">改变值</button>
</template>
<script setup lang="ts">
import { ref, reactive, onMounted,nextTick } from 'vue'
let message = ref<string>('我是小满')
let div = ref<HTMLElement>()
const change = async () => {
message.value = '小满最骚'
await nextTick() // 必须加上nextTick才会打印出"小满最骚",否则就算改变了还是打印'我是小满'
console.log(div.value?.innerHTML)
}
</script>
<style scoped></style>
原因:await将函数暂停在当前行,直到返回的Promise对象resolve完成,模板更新(相当于watch监听)会维护三个队列,其中默认为pre(watch中的语句在模板更新之前调用),因此没有nextTick的话console.log打印出的仍然是模板更新之前的内容,而nextTick相当于一个返回Promise的微任务,它始终在模板更新之后执行,因此可以将change函数剩余的部分全部放到模板更新之后再调用,这样就能保证获取到最新的数据了