Vue 3 reactive 数组直接索引赋值或修改 length 不触发更新,因 Proxy 无法拦截;应使用变异方法、splice、ref 包裹或 triggerRef,并确保 v-for 的 key 唯一稳定。

Vue 3 的 reactive 对数组的响应式处理有天然限制:直接通过索引赋值(如 arr[0] = newValue)或修改 length(如 arr.length = 0),**不会触发视图更新**。这不是 bug,而是 Proxy 机制的特性决定的——它无法拦截这些操作。
为什么 reactive 数组的某些操作不响应?
Proxy 只能拦截对象属性的读写(get/set)、数组方法调用等,但以下操作绕过了拦截:
-
arr[index] = value—— 直接写入索引位置,不是 set 操作 -
arr.length = 0—— 修改 length 属于属性赋值,但 Proxy 默认不追踪 length 变更 -
arr.push等原生方法虽被重写,但若你用的是未被代理的“副本”或非 reactive 值,也会失效
正确更新 reactive 数组的 4 种方式
确保每次变更都走响应式通道:
-
用 Vue 提供的数组变异方法:
push()、pop()、shift()、unshift()、splice()、sort()、reverse()—— 这些都被重写了,会触发更新 -
用
splice(index, deleteCount, ...items)替代索引赋值:arr.splice(0, 1, newValue)更新第 0 项 -
用
ref包裹数组(适合简单场景):虽然 reactive 更常用,但const list = ref([])后,list.value = [...list.value]或list.value = newList都能强制更新 -
用
proxy+triggerRef(进阶):对已用 reactive 声明的数组,手动通知更新:import { triggerRef } from 'vue'; triggerRef(arr)—— 适用于 splice 失效的极少数边界情况(如嵌套深层数组)
列表渲染时 key 不唯一?视图乱套的隐形杀手
即使数组响应式更新了,v-for 的 :key 若重复或用 index,会导致复用错误、状态错位、输入框失焦等问题:
- ❌ 错误写法:
<div v-for="(item, i) in list" :key="i">(新增/删除后 index 变,key 失效) - ✅ 正确写法:
<div v-for="item in list" :key="item.id">(id 必须唯一且稳定) - ⚠️ 若数据无 id,可借助
crypto.randomUUID()初始化,但需确保不随渲染重生成
避免非响应式“替换”:别把 reactive 当普通对象用
常见误区:
- ❌
state.list = state.list.filter(...)—— filter 返回新数组,但 reactive 不自动代理新数组(除非用shallowRef或重新赋值给 ref) - ✅ 正确做法:
state.list.splice(0, state.list.length, ...state.list.filter(...))(就地清空并填入) - ✅ 或改用
ref:const list = ref([]); list.value = list.value.filter(...)
不复杂但容易忽略:数组响应式靠的是“方法调用路径”和“代理完整性”,不是魔法。盯住操作是否触发了 proxy handler,再检查 key 是否稳定,90% 的列表不更新问题就解决了。


















