Vue 3 中数组响应式失效主因是操作绕过 Proxy 追踪:push/pop/shift/unshift/splice/sort/reverse 及 ref 整体赋值可触发更新;直接索引赋值、改 length、Object.assign 或展开赋值则失效。

Vue 3 的 reactive 对数组本身是响应式的,但视图不更新通常不是响应式失效,而是修改方式绕过了 Proxy 的追踪机制。关键在于:数组的响应式能力有明确的操作边界,不是所有“看起来改了数组”的写法都能被侦测。
哪些数组操作会触发视图更新
Vue 3 基于 Proxy 对数组做了增强,以下操作可直接触发依赖更新:
- 调用内置变异方法:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
- 用 ref 包裹后整体赋值:list.value = newArray
- 用 reactive 包裹后,通过 splice 替换某项:arr.splice(index, 1, newItem)
哪些写法看似有效实则失效
这些操作会改变数组内容,但 Proxy 无法拦截,因此不通知依赖更新:
审查 Vue 管理后台的变更请求(Vue 2 + Element UI,Vue 3 + Element Plus)。重点关注最小化变更实现、上线风险检查以及回归检查清单生成。
- 直接通过索引赋值:arr[0] = newValue
- 直接修改 length:arr.length = 0
- 用 Object.assign 或展开运算符覆盖内部:Object.assign(arr, [1,2,3]) 或 arr = [...newArr](后者更严重——直接丢失响应式引用)
正确更新数组某一项的实用方式
假设 const list = reactive([1, 2, 3]),想把第 1 项改为 99:
立即学习“前端免费学习笔记(深入)”;
- 推荐用 splice:list.splice(1, 1, 99) —— 语义清晰、原地修改、完全响应式
- 嵌套响应式对象:若数组项是对象(如 reactive([{id:1, name:'a'}])),可直接改属性:list[0].name = 'new a'(因为对象属性本身可被 Proxy 追踪)
- 用 ref 替代 reactive:const list = ref([]),后续赋值 list.value = newData,或 list.value[index] = val(需确保操作在 .value 上)
特别注意:别意外丢失响应式引用
这是高频隐蔽问题:
- ❌ 错误:list = apiResponseData —— 直接赋值普通数组,原 reactive 引用被覆盖
- ✅ 正确:list.splice(0, list.length, ...apiResponseData) 或 list.push(...apiResponseData)
- ✅ 或封装一层:const state = reactive({ list: [] }),再赋值 state.list = apiResponseData(因 state 是响应式,其属性 list 的赋值会被追踪)

















