vue3 数据响应式遇到的问题
2026年4月17日 17:56
问题背景
是在vue2项目升级vue3项目中遇到的,因为升级项目并没有使用vue的Composition api 而是使用Options api,所有复杂类型变量默认使用reactive进行响应式,问题也是从这出现的
- 对象数组中,使用索引值更改数据,数据变化了页面没有变化
- 类似代码 - options api使用的是this指针方式,但是问题是一样的
cosnt arr = reactive({
arr1:[
{
"name": "test",
"name2": "test2",
"name3": "test3",
},
{
"name": "test",
"name2": "test2",
"name3": "test3",
}
]
})
arr["arr1"][0] = {"name": "test11","name2": "test22","name3": "test33",}
这个时候我们从vue3的源代码入手,分析原因,具体只需要看proxy 的 get方法
源代码地址 packages\reactivity\src\baseHandlers.ts
有个BaseReactiveHandler方法
![]()
当我们触发get方法时,如果还是复杂类型,需要在调用reactive将其转化成响应式,所以Vue的依赖收集是"按需"的,具有一种懒惰性质,层级较深的复杂类型数据不是在声明式就被全部转化成响应式,而是在获取时逐层转化的
这个时候我们回看我们的问题,当我们执行arr["arr1"][0] = {"name": "test11","name2": "test22","name3": "test33",}的时候,只触发了arr["arr1"],但是再往下层级的并没有被转化成响应式,所以此时我们可以这样去解决
consr newArr = arr["arr1"]
newArr[0] = {"name": "test11","name2": "test22","name3": "test33",}
arr["arr1"] = newArr[0]
2. 解构失去响应式
const test = reactive({
arr: { name: '111'}
})
// 解构会失去响应性!
const { arr } = test
// 修改 user 不会触发界面更新
arr.name = '李四' //界面不更新
//解决方案
// 1、
const { arr } = toRefs(test)
// 2、尽量不要解构响应式数据
3. 新增属性不响应
const test = reactive({
arr: { name: '111'}
})
// 修改 user 不会触发界面更新
test.arr.age= 22 //界面不更新
// 解决方法 使用 Object.assign
Object.assign(test.arr, { age: 22 })
总结
所以在vue3 开发中,如果使用options api方式,就需要尽量注意多层嵌套对象,如果使用Composition api,尽量使用 ref 去定义变量,并且针对嵌套层级较深的变量最好使用ShallowRef ShallowReactive 用于优化深层嵌套对象的性能问题