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:拿到的 inforeactive 生成的代理对象本身 (而非原始值),因此访问 / 修改 info.name 仍会触发响应式的依赖收集和更新;
  3. 解构嵌套对象的属性 const { name } = info:拿到的是 info.name原始值(如字符串 "张三"),而非代理属性,因此丢失响应式。
相关推荐
QQ1__8115175156 小时前
Spring boot名城小区物业管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】
前端·vue.js·spring boot
IT枫斗者6 小时前
前端部署后如何判断“页面是不是最新”?一套可落地的版本检测方案(适配 Vite/Vue/React/任意 SPA)
前端·javascript·vue.js·react.js·架构·bug
難釋懷8 小时前
Vue混入
前端·javascript·vue.js
訾博ZiBo8 小时前
Vue3响应式高阶用法之toRaw()
javascript·vue.js·ecmascript
涵涵(互关)11 小时前
GoView各项目文件中的相关语法2
前端·javascript·vue.js
焰火199912 小时前
[Vue]可重置的响应式状态reactive
前端·vue.js
源码宝12 小时前
基于 SpringBoot + Vue 的医院随访系统:技术架构与功能实现
java·vue.js·spring boot·架构·源码·随访系统·随访管理
老王以为12 小时前
为什么 React 和 Vue 不一样?
前端·vue.js·react.js
web打印社区12 小时前
2026最新Web静默打印解决方案,无插件无预览,完美替代Lodop
前端·javascript·vue.js·electron·pdf
Forever7_14 小时前
Vue 全局监控用户行为,最强方案!
vue.js