在 Vue(尤其是 Vue 2) 中,data 里的数组操作有些方法能直接触发视图更新,有些则不会。
原因是 Vue 2 用的是 基于 Object.defineProperty 的响应式系统,它对数组的方法做了特别的处理,但有些变化检测不到。
可以触发视图更新的数组方法
Vue 2 内部 重写 了这些原型方法,调用它们时会触发视图更新:
修改数组内容的变更方法:
push() // 末尾添加
pop() // 删除最后一个
shift() // 删除第一个
unshift() // 开头添加
splice() // 删除/替换/添加
sort() // 排序
reverse() // 反转
这些方法都能 触发响应式更新,因为 Vue 已经拦截它们。
不能触发视图更新的情况
Vue 无法检测 以下数组变动:
1.直接通过索引修改元素
this.list[1] = 'new value'; // ❌ 不会触发更新
2.直接修改数组长度
this.list.length = 0; // ❌ 不会触发更新
原因:Object.defineProperty 不能拦截数组索引的变化,也不能感知 length 的变化。
解决办法
方法 1:Vue.set() 或 this.$set()
// 替换索引 1 的值
this.$set(this.list, 1, 'new value');// 或者
Vue.set(this.list, 1, 'new value');
方法 2:用 splice() 代替
// 把索引 1 的值替换成 new value
this.list.splice(1, 1, 'new value');// 清空数组
this.list.splice(0);
Vue 3 的区别
Vue 3 用了 Proxy,可以直接监听索引赋值和 length 改变,所以:
this.list[1] = 'new value'; // 会更新
this.list.length = 0; // 会更新
Vue 3 基本没有这个限制。