You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何修改普通对象会影响响应式对象?二者并非同一对象

Vue3中ref嵌套对象的响应式表现解析

问题代码

const cellsArray = Array.from(Array(fieldSize.height), (_, y) =>
  Array.from(Array(fieldSize.width), (_, x) => new Cell(y, x))
);

const fieldCells = ref(cellsArray);

console.log(fieldCells.value[0][0] == cellsArray[0][0]);    // false

function increase() {
  cellsArray[0][0].x += 1;

  console.log(cellsArray[0][0].x);          // 1, 2, 3, 4 and so on
  console.log(fieldCells.value[0][0].x);    // 1, 2, 3, 4 and so on
}

问题描述

创建了Cell类实例的二维数组cellsArray,再通过ref将其转为响应式数组fieldCells。已知ref会把cellsArray包装为Proxy,fieldCells是不同的数组,从fieldCells.value[0][0] == cellsArray[0][0]输出false可知二者对应元素并非同一对象,但修改任一数组元素的x属性时,另一数组对应元素的x属性也会同步变化,无法理解该现象的原因。

原因解析

核心逻辑在于Vue3响应式系统对嵌套对象的包装规则:

  • 当你用ref(cellsArray)时,Vue会先把外层数组包装成Proxy对象(即fieldCells.value),再递归对数组内的内层数组也做Proxy包装——这就是为什么fieldCells.value和cellsArray不是同一个数组引用。
  • 但对于数组中的Cell实例(自定义类对象),Vue的响应式处理不会创建一个全新的Cell实例,而是给原始的Cell实例套一层Proxy代理。也就是说:
    • cellsArray[0][0]是原始的Cell实例
    • fieldCells.value[0][0]是该原始实例的Proxy代理对象
  • 二者不是同一个引用(所以==返回false),但代理对象的属性访问/修改会直接映射到原始实例的对应属性上。因此修改原始实例的x属性,代理对象读取的就是更新后的值;反之修改代理对象的x,也会同步到原始实例中,最终表现为两边的x属性同步变化。

内容的提问来源于stack exchange,提问作者devdevdove

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 11:00:56