「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函数。

相关推荐
dawn1912281 分钟前
SpringMVC 中的域对象共享数据
java·前端·servlet
newxtc38 分钟前
【爱给网-注册安全分析报告-无验证方式导致安全隐患】
前端·chrome·windows·安全·媒体
刘志辉1 小时前
vue传参方法
android·vue.js·flutter
dream_ready2 小时前
linux安装nginx+前端部署vue项目(实际测试react项目也可以)
前端·javascript·vue.js·nginx·react·html5
编写美好前程2 小时前
ruoyi-vue若依前端是如何防止接口重复请求
前端·javascript·vue.js
flytam2 小时前
ES5 在 Web 上的现状
前端·javascript
喵喵酱仔__2 小时前
阻止冒泡事件
前端·javascript·vue.js
GISer_Jing2 小时前
前端面试CSS常见题目
前端·css·面试
八了个戒2 小时前
【TypeScript入坑】什么是TypeScript?
开发语言·前端·javascript·面试·typescript
不悔哥2 小时前
vue 案例使用
前端·javascript·vue.js