为何修改普通对象会影响响应式对象?二者并非同一对象
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
相关产品推荐
相关产品推荐

