「Vue3学习篇」-isReactive()、shallowReactive()

『引言』

这次介绍两个API,分别为isReactive()、shallowReactive()。想知道这两个API是干什么的?一起接着往下看。

『isReactive()』

『定义』

【官方解释】 检查一个对象是否是由 reactive()shallowReactive() 创建的代理。

【我的理解】 isReactive()用于检查对象是否是由reactive创建的响应式代理。

『用法』

isReactive()是用来检测reactive类型的,如果是返回的是true,否则返回false。

『注意』

  • 如果该代理是readonly()创建的,但包裹了由reactive创建的另一个代理,它也会返回true。

『示例🌰』

xml 复制代码
<template>
  <div>
    <h1>isReactive应用</h1>
    <p>姓名:{{name.petName}}</p>
    <p>年龄:{{age}}岁</p>
    <p>爱好:{{hobbies.hobbyOne}} 、 {{ hobbies.hobbyTwo }}</p>
    <p>地址:{{address.provice}} - {{ address.city }} </p>
    <p>描述:{{description.character}}</p>
    <p>最喜欢的颜色:{{favoriteColor.coloeOne}}&{{ favoriteColor.colorTwo }}</p>
    <p>最想去的地方:{{place.provice}}{{ place.city }}</p>
    <button @click="isReactiveFun">
      点击按钮显示判断结果
    </button> 
  </div> 
</template>

<script setup>
import { ref, reactive, shallowRef, readonly, isReactive, shallowReactive } from 'vue'
    
    const name = ref({
      petName: 'wnxx'
    })
    const age = ref(3)
    const hobbies = reactive({
      hobbyOne: '打羽毛球',
      hobbyTwo: '旅游'
    })
    const address = shallowRef({
      provice: '云南省',
      city: '丽江市'
    })
    const description = readonly(
      reactive({
      character: '非常的可爱,特别喜欢吃蜂蜜!'
    })
    )
    const favoriteColor = shallowReactive({
      coloeOne: '薄荷绿',
      colorTwo: '天蓝色'
    })
    const place =  readonly(
      ref({
        provice: '广西省',
        city: '桂林市'
      })
    )
    // 测试函数
    const isReactiveFun = () => {
        console.log(isReactive(name.value), 'name')
        console.log(isReactive(age), 'age')
        console.log(isReactive(hobbies), 'hobby')
        console.log(isReactive(address.value), 'address')
        console.log(isReactive(description), 'description')
        console.log(isReactive(favoriteColor), 'favoriteColor')
        console.log(isReactive(place.value), 'place') 
    }  
</script>

『显示结果』

『isReactive源码』

isReactive源码如下⬇️:

scss 复制代码
export function isReactive(value: unknown): boolean {
  if (isReadonly(value)) {
    return isReactive((value as Target)[ReactiveFlags.RAW])
  }
  return !!(value && (value as Target)[ReactiveFlags.IS_REACTIVE])
}

首先调用isReadonly,判断是否是readonly API创建的对象

isReadonly源码如下⬇️:

typescript 复制代码
export function isReadonly(value: unknown): boolean {
  return !!(value && (value as Target)[ReactiveFlags.IS_READONLY])
}
  • ReactiveFlags.IS_READONLY是一个字符串,值为:__v_isReadonly
  • 判断当前对象的__v_isReadonly属性是否是true,并返回。

然后是由readonly api创建的话,就通过调用isReactive,对当前对象的RAW属性进行判断

最后判断readonly源对象是否为reactive不是的话,就通过判断__v_isReactive是否为true,返回最后结果。

  • ReactiveFlags.RAW是一个字符串,值为:__v_raw
  • ReactiveFlags.IS_READONLY也是一个字符串,值为:__v_isReactive

『shallowReactive()』

『定义』

【官方解释】reactive() 的浅层作用形式。

reactive() 不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

【我的理解】 shallowReactive()用来创建一个响应式对象。shallowReactive()跟踪其自身property的响应式,会忽略对象中的嵌套属性的响应式更新。任何使用ref的属性都不会被代理自动解包。

『用法』

javascript 复制代码
import { shallowReactive} from 'vue' 

setup(){ 
    let person = shallowReactive({ 
        //只考虑第一层数据的响应式 
        name:'wnxx', 
        address:{
          provice: '云南省',
          city: '丽江市'
        }
    }) 
}

『注意』

  • ⚠️谨慎使用

浅层数据结构应该只用于组件中的根级状态。请避免将其嵌套在深层次的响应式对象中,因为它创建的树具有不一致的响应行为,这可能很难理解和调试。

  • 对象数据中的,浅层和深层数据都要做处理时,一定要慎用!!!
  • shallowReactive()通常是,当我们需要创建一个响应式对象,但是不希望其嵌套属性也响应式更新时,可以使用这个API。

『示例🌰』

使用shallowReactive创建一个响应式对象infoData,其中包含几个直接属性name等等和两个嵌套属性addresshobby。然后对数据进行修改,添加操作,观察视图的变化情况。

xml 复制代码
<template>
  <div>
    <h1>shallowReactive应用</h1>
    <p>姓名:{{infoData.petName}}</p>
    <p>年龄:{{infoData.age}}岁</p>
    <p>爱好:{{infoData.hobbies.hobbyOne}} 、 {{ infoData.hobbies.hobbyTwo }}</p>
    <p>地址:{{infoData.address.provice}} - {{ infoData.address.city }} </p>
    <p v-if="infoData.description">描述:{{infoData.description}}</p>
    <button @click="modifyNameFun">
      修改姓名
    </button> 
    <button @click="addDescriptionFun">
      添加属性
    </button> 
    <button @click="modifyAddressFun">
      修改地址
    </button> 
  </div> 
</template>

<script setup>
import { shallowReactive } from 'vue'
    
    const infoData = shallowReactive({
      petName: 'pupu',
      age: 3,
      hobbies: {
        hobbyOne: '打羽毛球',
        hobbyTwo: '旅游'
      },
      address: {
        provice: '云南省',
        city: '丽江市'
      }
    })
    
    // 修改姓名函数
    const modifyNameFun = () => {
      //  修改infoData对象的直接属性,会触发响应式更新
      infoData.petName = 'wnxx'
    }

    // 修改地址函数
    const modifyAddressFun = () => {
        //  修改infoData对象的嵌套属性,不会触发响应式更新
        infoData.address.provice = '广西省',
        infoData.address.city = '桂林市'
        console.log('地址信息已经更新完成')
        console.log(infoData.address, '地址')
    }

    // 添加新的属性
    const addDescriptionFun =() => { 
        infoData.description = '非常的可爱,特别喜欢吃蜂蜜!'
    }
</script>

『显示效果』

『代码解析』

由效果图可以看到:

当修改infoData.petName属性时,姓名属性视图上发生,会触发响应式更新。

当添加infoData.description属性时,描述属性出现在视图中,会触发响应式更新。

当修改infoData.address.proviceinfoData.address.city属性时,地址属性控制台打印信息显示已完成更新操作,视图上未发生变化,不会触发响应式更新。

之所以会是这种效果就是因为shallowReactive是浅层作用形式。对于修改,添加直接属性是会触发更新,嵌套属性是不会触发更新的。

如果我们想要响应式更新嵌套属性,需要使用reactive或者ref来创建响应式对象。

『shallowReactive源码』

shallowReactive源码如下⬇️:

typescript 复制代码
export function shallowReactive<T extends object>(
  target: T
): ShallowReactive<T> {
  return createReactiveObject(
    target,
    false,
    shallowReactiveHandlers,
    shallowCollectionHandlers,
    shallowReactiveMap
  )
}

『参数说明』:

  • 第一个参数还是target。
  • 第二个是isReadonly,为false。
  • 第三个参数shallowReactiveHandlers是shallowReactive对应的处理函数。
  • 第四个参数是对于集合类型的对象进行处理的shallowReactive所对应的函数。

内部调用了createReactiveObject函数。

相关推荐
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment3 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax