VUE3-ref包裹object对象类型

文章探讨了在Vue3中,ref如何实现对基本类型和对象类型的响应式。对于基本类型,使用了Object.defineProperty;而对于对象类型,Vue3结合了Object.defineProperty和Proxy来实现深层响应式。示例代码展示了如何修改和响应用户信息的变化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

VUE3-ref包裹object对象类型

ref不同类型下,实现的响应方式

基本类型 string number undefined null boolean

使用Object.defineProperty实现的

img

引用类型 object

// 如果你采用这种value直接赋值的方式,表示这种响应式是基于Object.defineProperty的
userRefImpl.value = {
  name: '张三',
  age: 50,
  addr: {
    city: '杭州1',
    street: '四季青街道1'
  }
}
// 下面这种使用value.的方式则使用的就是Proxy
// userRefImpl.value是一个代理对象Proxy: userProxy对象。
userRefImpl.value.name = '李四'
userRefImpl.value.age = '30'

// 修改地址信息
userRefImpl.value.addr.city = '上海'
userRefImpl.value.addr.street = '宁一路'

img

代码

<template>
  <div>计数:{{counterRefImpl}}</div>
  <button @click="counterRefImpl++">点我数字加一</button>
  <div>姓名:{{userRefImpl.name}}</div>
  <div>年龄:{{userRefImpl.age}}</div>
  <div>市区:{{userRefImpl.addr.city}}</div>
  <div>街道:{{userRefImpl.addr.street}}</div>
  <button @click="modifyUser">修改用户信息</button>
</template>
<script>
  import {
    ref
  } from 'vue'
  export default {
    setup() {
      // data
      // 如果ref包裹的是一个基本数据类型,响应式是如何实现的?Object.defineProperty
      let counterRefImpl = ref(100)
      console.log('ref_base', counterRefImpl);

      // 如果ref包裹的是一个对象,响应式是如何实现的?Object.defineProperty + Proxy 实现的
      // Proxy实现的响应式,对象中的对象,都有响应式处理
      let userRefImpl = ref({
        name: 'zhangsan',
        age: 21,
        addr: {
          city: '杭州',
          street: '四季青街道'
        }
      })
      console.log('ref_object', userRefImpl);

      function modifyUser() {
        // 这种修改时有响应式处理的
        counterRefImpl.value = 200

        // 对于userRefImpl对象来说,应该怎么改,才能有响应式呢?
        // 如果你采用这种value直接赋值的方式,表示这种响应式是基于Object.defineProperty的
        // userRefImpl.value = {
        //   name: '张三',
        //   age: 50,
        //   addr: {
        //     city: '杭州1',
        //     street: '四季青街道1'
        //   }
        // }

        // userRefImpl.value是一个代理对象Proxy: userProxy对象。
        userRefImpl.value.name = '李四'
        userRefImpl.value.age = '30'

        // 修改地址信息
        userRefImpl.value.addr.city = '上海'
        userRefImpl.value.addr.street = '宁一路'
      }
      return {
        counterRefImpl,
        userRefImpl,
        modifyUser
      }
    }
  }
</script>

文章涉及内容:
vue3、Proxy、Object.defineProperty

### Vue3 中避免 `ref` 数据成为 `Proxy(Array)` 的方法 在 Vue3 中,当使用 `ref` 或者 `reactive` 创建响应式数据时,默认情况下这些数据会被封装在一个 `Proxy` 对象内。对于数组类型的 `ref` 变量,在访问其内部值时会遇到 `Proxy(Array)` 这样的情况。 为了获取到未被代理的原始数组,可以直接通过 `.value` 属性来访问 `ref` 所指向的实际值[^1]。然而,如果希望完全绕过 `Proxy` 并获得纯净的数据结构,则有几种不同的策略可供选择: #### 方法一:解构赋值 利用 JavaScript 的扩展运算符(spread operator),可以从 `Proxy` 包装的对象中提取出所有的元素并构建一个新的独立数组实例。 ```javascript const originalData = [&#39;item1&#39;, &#39;item2&#39;]; const dataRef = ref(originalData); // 使用扩展运算符复制数组内容至新变量 const pureArray = [...dataRef.value]; console.log(pureArray); // 输出: ["item1", "item2"] ``` 这种方法简单有效,适用于大多数场景下的需求[^3]。 #### 方法二:转换为 JSON 字符串再解析回对象/数组 另一种方式是先将整个 `Proxy` 结构序列化为 JSON 字符串形式,然后再反序列化得到纯粹的对象或数组表示法。 ```javascript const jsonDataString = JSON.stringify(dataRef.value); const parsedPureArray = JSON.parse(jsonDataString); console.log(parsedPureArray); // 输出: ["item1", "item2"] ``` 需要注意的是此方法可能会丢失一些特殊属性或函数成员,因此仅限于基本类型的数据处理。 #### 方法三:自定义 getter 函数 还可以编写一个辅助性的 getter 函数用于返回去除了 `Proxy` 包裹后的实际数值。 ```javascript function getRawValue(proxyObject){ return Array.isArray(proxyObject)? [...proxyObject]: {...proxyObject}; } let rawData = getRawValue(dataRef.value); console.log(rawData); // 输出: ["item1", "item2"] ``` 这种方式提供了更大的灵活性,并且可以根据具体的应用逻辑调整实现细节。 综上所述,虽然无法阻止 Vue 自动应用 `Proxy` 来增强响应性特性,但可以通过上述手段轻松地取得未经修饰的基础数据副本供后续操作使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值