所遇到的响应式问题

问题背景

是在vue2项目升级vue3项目中遇到的,因为升级项目并没有使用vue的Composition api 而是使用Options api,所有复杂类型变量默认使用reactive进行响应式,问题也是从这出现的

  1. 对象数组中,使用索引值更改数据,数据变化了页面没有变化
  • 类似代码 - options api使用的是this指针方式,但是问题是一样的
javascript 复制代码
  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"],但是再往下层级的并没有被转化成响应式,所以此时我们可以这样去解决

javascript 复制代码
"test11","name2": "test22","name3": "test33",} arr["arr1"] = newArr[0]
  1. 解构失去响应式
javascript 复制代码
const test = reactive({
   arr: { name: '111'}    
})    
   // 解构会失去响应性!    
   const { arr } = test    
   // 修改 user 不会触发界面更新    
   arr.name = '李四'  //界面不更新
   //解决方案   
   // 1、    
   const { arr } = toRefs(test)    
   // 2、尽量不要解构响应式数据
  
  1. Object新增属性不响应
javascript 复制代码
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 用于优化深层嵌套对象的性能问题

相关推荐
涛涛ing17 小时前
狂揽2.4万星标:一行命令,AI会自己找技能了
前端
Csvn17 小时前
🚨 JSON.stringify 的 6 个隐藏坑:为什么你的数据序列化后"消失"了?
前端
aircrushin17 小时前
Claude 5 之后,上下文工程该做减法了
前端·人工智能·后端
huabuyu17 小时前
CLS 自动化归因及自愈:让系统自己定位根因、修复并验证
前端·javascript
C++、Java和Python的菜鸟17 小时前
第13章 前端Web实战(Tlias案例)
前端·javascript·vue.js
用户69190268133917 小时前
React 组件间通信全解析:从父子到跨级
前端·javascript
echoVic17 小时前
同一个 bug,我在 WebGPU 渲染器里犯了两轮:一帧内多次写同一块 buffer
前端·webgl·图形学
胡萝卜术17 小时前
数据主权与渲染防线:从受控组件到性能优化的完整图景
前端·javascript·面试
DFT计算杂谈17 小时前
FeSe超薄膜在CaF2衬底上的电子结构DFT研究
java·服务器·前端
BreezeJiang17 小时前
父组件一更新,子组件就必须跟着更新吗?从 memo 走到 useCallback
前端·javascript