Vue 3 响应式自动更新
Vue 3 中 ref 和 reactive 的数据修改会自动触发组件重新渲染,无需手动操作:
const count = ref(0);
count.value++; // 自动触发更新
const state = reactive({ name: 'hello' });
state.name = 'world'; // 自动触发更新
强制重建组件:修改 :key
当需要完全销毁并重新创建一个组件(而不只是更新数据)时,修改 :key 是最推荐的方式:
<template>
<MyComponent :key="refreshKey" :data="data" />
<button @click="refreshKey++">强制刷新</button>
</template>
<script setup>
import { ref } from 'vue';
const refreshKey = ref(0);
</script>
:key 变化会让 Vue 销毁旧组件实例并创建新的,适合需要重置内部状态的场景。
shallowRef 深层修改:triggerRef
shallowRef 只追踪引用本身的变化,不追踪对象内部属性:
import { shallowRef, triggerRef } from 'vue';
const data = shallowRef({ list: [] });
data.value.list.push(1); // 不触发更新!
triggerRef(data); // 手动通知 Vue 重新渲染
非必要不用 shallowRef,直接用 ref 更简单。
nextTick:等待 DOM 更新完成
数据变更后,DOM 不会立即同步更新(Vue 批量异步更新),需要 nextTick 等待:
import { ref, nextTick } from 'vue';
const visible = ref(false);
visible.value = true;
await nextTick();
// 此时 DOM 已更新,可以安全操作 DOM 元素
const el = document.querySelector('.new-element');
常见陷阱:解构 reactive 丢失响应式
const state = reactive({ count: 1, name: 'hello' });
// 错误:解构后 count 是普通变量,不是响应式
const { count } = state;
count; // 修改不会触发更新
// 正确:用 toRefs 保留响应式
import { toRefs } from 'vue';
const { count, name } = toRefs(state);
count.value++; // 正确触发更新
ref 不存在这个问题,因为 ref 返回的是包装对象,count.value 始终访问同一个响应式引用。
Vue 2 迁移注意
Vue 2 中直接对数组索引赋值、添加新属性不响应,需要 $set:
// Vue 2
this.$set(this.arr, 0, newValue);
this.$set(this.obj, 'newKey', 1);
Vue 3 用 Proxy 实现响应式,这两种写法都能正确追踪,不需要 $set。
$forceUpdate(不推荐)
import { getCurrentInstance } from 'vue';
const instance = getCurrentInstance();
instance.proxy.$forceUpdate();
$forceUpdate 只强制当前组件实例重渲染,不更新子组件,且不解决数据不响应的根本问题。遇到更新问题应优先排查响应式数据的使用方式,而不是调用 $forceUpdate。
