ref数组管理核心是通过.value重新赋值触发响应式更新;因不依赖proxy拦截数组方法,故对索引赋值、length修改等操作天然响应,适合整批替换、过滤、排序等场景。

Ref 数组管理的核心在于:用 ref 包裹整个数组,再通过 重新赋值(而非直接修改)来触发响应式更新。它不依赖 Proxy 对数组方法的拦截,而是靠 .value 的引用变更通知 Vue 重渲染。
为什么 ref 数组比 reactive 数组更适合列表更新?
reactive 数组对 arr[0] = x 或 arr.length = 0 无响应,因为 Proxy 拦截不到这些操作;而 ref 数组只要 list.value = newList,就等于替换了整个响应式引用,视图必然更新。
- 适合频繁整批替换、过滤、排序等场景(如搜索结果刷新、分页加载)
- 写法直观,不需记哪些数组方法“被重写”
- 配合
v-for使用时,key 稳定即可,无需额外处理响应性穿透
如何用 ref 管理并更新列表数据?
声明时用 ref([]),后续所有更新都走 .value = ... 赋值路径:
- 追加元素:
list.value = [...list.value, newItem] - 删除某项:
list.value = list.value.filter(item => item.id !== targetId) - 更新某一项:
list.value = list.value.map(item => item.id === id ? {...item, name: 'new'} : item) - 清空数组:
list.value = [] - 替换全部:
list.value = apiResponseData
注意:避免常见误操作
以下写法不会触发更新,即使用了 ref:
-
list.value.push(item)—— 改了原数组,但.value引用没变 -
list.value[0] = {...list.value[0], done: true}—— 同上,引用未变 -
Object.assign(list.value, newData)—— 只改内容,不换引用
本质是:Vue 的 ref 响应式靠的是 赋值时 .value 的引用变化,不是数组内部变化。
进阶:结合 shallowRef 提升性能(大列表适用)
如果列表项本身是普通对象(非 reactive),且你只关心整体替换而非单项响应,可用 shallowRef 减少深层代理开销:
const list = shallowRef([{id:1,name:'a'}, {id:2,name:'b'}])- 更新仍用
list.value = newList - 但
list.value[0].name = 'x'不会触发更新 —— 这正是你想要的“浅层”行为










