在 Vue 3 中,除了 markRaw
和 reactive
结合的方式,还有以下几种常见的手动更新虚拟 DOM 的方式:
1. 使用 triggerRef
(针对 ref
创建的数据)
ref
是 Vue 3 中创建响应式数据的一种方式,当手动修改 ref
的 .value
属性后,默认情况下不会立即触发更新。可以使用 triggerRef
函数来手动触发更新。
<template>
<div>
<p>{
{ count }}</p>
<button @click="incrementManually">手动增加计数</button>
</div>
</template>
<script setup>
import { ref, triggerRef } from 'vue';
const count = ref(0);
const incrementManually = () => {
// 手动修改 ref 的值
count.value++;
// 手动触发更新
triggerRef(count);
};
</script>
2. 使用 nextTick
nextTick
用于在下次 DOM 更新循环结束之后执行延迟回调。虽然它本身不是直接手动更新虚拟 DOM,但可以结合数据修改来确保在数据更新后,DOM 已经更新完毕时执行某些操作,也可以变相实现手动控制更新流程的效果。
<template>
<div>
<p>{
{ message }}</p>
<button @click="updateMessage">更新消息</button>
</div>
</template>
<script setup>
import { ref, nextTick } from 'vue';
const message = ref('初始消息');
const updateMessage = async () => {
// 修改数据
message.value = '新消息';
// 等待 DOM 更新完成
await nextTick();
// 此时 DOM 已经更新,可以进行后续操作
console.log('DOM 已更新');
};
</script>
3. 强制组件重新渲染
可以通过改变组件的 key
属性来强制组件重新渲染,从而达到手动更新虚拟 DOM 的目的。当 key
值发生变化时,Vue 会认为这是一个全新的组件实例,会重新创建并渲染该组件。
<template>
<div>
<MyComponent :key="componentKey" />
<button @click="forceRerender">强制重新渲染</button>
</div>
</template>
<script setup>
import { ref } from 'vue';
import MyComponent from './MyComponent.vue';
const componentKey = ref(1);
const forceRerender = () => {
// 改变 key 值,强制组件重新渲染
componentKey.value++;
};
</script>
4. 使用 shallowRef
和 triggerRef
shallowRef
创建的是一个浅层响应式引用,只有 .value
属性本身是响应式的,而 .value
指向的对象内部的属性变化不会触发更新。可以结合 triggerRef
手动触发更新。
<template>
<div>
<p>{
{ person.name }}</p>
<button @click="updateName">更新姓名</button>
</div>
</template>
<script setup>
import { shallowRef, triggerRef } from 'vue';
const person = shallowRef({ name: '张三' });
const updateName = () => {
// 手动修改对象属性
person.value.name = '李四';
// 手动触发更新
triggerRef(person);
};
</script>
这些方法在不同的场景下有各自的用途,开发者可以根据具体需求选择合适的方式来手动更新虚拟 DOM。