Vue 3 响应式陷阱:ref/reactive 的选择、解构丢响应与 shallowRef 优化
test12026-09-1210 次阅读
ref 与 reactive 怎么选
Vue 3 的响应式有两条入口:ref 包任意类型(访问要加 .value),reactive 只包对象且自动深度代理。基本类型用 ref,对象类型两者都能用,但 reactive 在重新赋值时有个大坑。
import { ref, reactive } from 'vue';
const count = ref(0);
count.value++; // ref 必须 .value
const state = reactive({ n: 0 });
state.n++; // reactive 直接点属性
解构会丢响应
这是最常见的问题:从 reactive 对象解构出来的属性,脱离了原对象就不再是响应式的。
const state = reactive({ count: 0, user: { name: 'a' } });
// 错误:count 变成普通数字,后续修改不触发更新
const { count } = state;
count = 1; // 视图不会变
// 正确:用 toRefs 把每个属性转成 ref
const { count: c } = toRefs(state);
c.value = 1; // 视图更新
reactive 重新赋值会断引用
reactive 对象不能用 = 整体替换,否则新对象与原引用脱钩,模板里还是旧的那份。
const list = reactive([1, 2, 3]);
// 错误:list 现在指向新数组,但模板绑定的是旧引用
list = [4, 5, 6];
// 正确做法一:用 ref 包数组,整体替换仍保持响应
const list = ref([1, 2, 3]);
list.value = [4, 5, 6];
// 正确做法二:原地修改
list.length = 0;
list.push(4, 5, 6);
大对象用 shallowRef 省性能
当状态是一个很大的对象或第三方实例(如图表、编辑器),你并不需要对它内部做深度代理,只在替换整体时触发更新即可。shallowRef 只追踪 .value 的替换,不递归代理。
import { shallowRef } from 'vue';
const editor = shallowRef(null);
// 只在赋新值时更新,内部字段变化不会触发
editor.value = createEditor();
editor.value.setOption('theme', 'dark'); // 不会触发视图更新
小结
- 基本类型一律 ref,访问记得 .value。
- 对象需要重新整体赋值,优先用 ref 而不是 reactive。
- 解构 reactive 属性用 toRefs,否则丢响应。
- 大对象或外部实例用 shallowRef 减少代理开销。
T
test1
文章作者
ref 与 reactive 怎么选 Vue 3 的响应式有两条入口:ref 包任意类型(访问要加 .value),r...
- 分类
- 技术
- 发布时间
- 2026-09-12
- 字数
- 约 1238 字
- 阅读
- 10 次
