vue3响应式解构注意

reactive 的响应式是深度绑定 的(默认递归代理所有嵌套对象),直接解构外层对象得到的嵌套对象,本质还是 reactive 生成的代理对象,因此它本身的响应式不会丢失;但如果对这个嵌套对象再做解构,就会回到之前的问题 ------ 解构其属性会丢失响应式。

代码示例(核心验证)

vue

xml 复制代码
<script setup lang="ts">
import { reactive } from 'vue'
// 创建响应式对象 const user = reactive({ name: '张三', age: 20 }) // 直接解构:丢失响应式 const { name, age } = user  对属性是基本类型时会丢失响应式这时需要用toRefs包裹
// 外层响应式对象,包含嵌套对象
const user = reactive({
  info: { // 嵌套对象,被 reactive 深度代理
    name: '张三',
    age: 20
  },
  hobby: ['篮球', '游戏'] // 嵌套数组,同样被深度代理
})
const user = reactive({ name: '张三', age: 20 }) // 用 toRefs 解构:保留响应式(转为 ref 类型) const { name, age } = toRefs(user) const changeName = () => { name.value = '李四' // 需通过 .value 修改,原对象会同步更新 console.log(user.name) // 输出 "李四" }



直接解构外层对象得到的嵌套对象
// 直接解构外层对象:拿到嵌套对象 info 和 hobby
const { info, hobby } = user

// 场景1:修改解构出的嵌套对象的属性(仍有响应式)
const changeInfo = () => {
  info.name = '李四' // ✅ 有响应式,视图会更新
  hobby.push('看书') // ✅ 有响应式,视图会更新
  console.log(user.info.name) // 输出 "李四"(和原对象同步)
}

// 场景2:对嵌套对象再解构(属性丢失响应式)
const { name, age } = info
const changeName = () => {
  name = '王五' // ❌ 非响应式,TS 提示无法赋值,视图无变化
  console.log(info.name) // 仍然是 "李四"
}

// 场景3:直接替换整个嵌套对象(仍有响应式)
const replaceInfo = () => {
  info.age = 25 // ✅ 改属性:响应式
  // 注意:如果直接替换整个嵌套对象,也需要通过原对象或解构的嵌套对象操作
  user.info = { name: '赵六', age: 30 } // ✅ 响应式
  // 或 info = { name: '赵六', age: 30 } ❌ 错误!解构的 info 是常量,不能直接赋值
}
</script>

<template>
  <div>原对象:{{ user.info.name }} - {{ user.info.age }} | {{ user.hobby }}</div>
  <div>解构嵌套对象:{{ info.name }} - {{ info.age }} | {{ hobby }}</div>
  <div>解构嵌套对象的属性:{{ name }} - {{ age }}</div>
  
  <button @click="changeInfo">修改嵌套对象属性</button>
  <button @click="changeName">修改解构的嵌套属性</button>
  <button @click="replaceInfo">替换嵌套对象</button>
</template>

运行结果:

  • 点击「修改嵌套对象属性」:所有关联视图(原对象、解构的嵌套对象)都会更新;
  • 点击「修改解构的嵌套属性」:视图无变化,嵌套对象的属性也没改;
  • 点击「替换嵌套对象」:原对象和解构的嵌套对象视图都会更新。

二、原理拆解:为什么嵌套对象仍有响应式?

  1. reactive 对对象做深度代理 :当创建 reactive({ info: { name: '张三' } }) 时,不仅外层对象被 Proxy 代理,内部的 info 对象也会被递归转为 Proxy 代理对象;
  2. 直接解构 const { info } = user:拿到的 info 是 reactive 生成的代理对象本身 (而非原始值),因此访问 / 修改 info.name 仍会触发响应式的依赖收集和更新;
  3. 解构嵌套对象的属性 const { name } = info:拿到的是 info.name 的原始值(如字符串 "张三"),而非代理属性,因此丢失响应式。
相关推荐
溪语流沙1 小时前
【Web全栈进阶】监控与告警:线上系统的“体检报告”
前端·vue.js·python·fastapi
卤蛋fg62 小时前
vue 下拉树组件 vxe-table-select 实现分页多选
vue.js
u0111026756 小时前
Vue 页面离开后还在轮询?统一清理计时器、监听器与观察器
前端·javascript·vue.js
大猩猩X6 小时前
vue 表格组件 vxe-table 实现多行编辑,支持增删改查与校验
前端·javascript·vue.js·vxe-table
ss2736 小时前
基于springboot+vue+mysql「校园二手教材循环交易」小程序,三端全跑通
vue.js·spring boot·mysql
冒险的豆子8 小时前
Proxy & Vue 响应式(合并精简版,适合面试)
前端·javascript·vue.js
Java后端的Ai之路8 小时前
前端技术Vue-18-视图中的渲染
前端·javascript·vue.js
濮水大叔19 小时前
函数式与对象式:前端架构的两种成本曲线
vue.js·react.js·函数式编程
vx_Biye_Design20 小时前
django房屋租赁推荐系统78455-计算机课程设计、毕业设计
vue.js·spring boot·后端·python·django·课程设计·express
林恒smileZAZ20 小时前
浏览器为什么加载不了超大图片
前端·vue.js·html5