『引言』
这次介绍两个API,分别为isReactive()、shallowReactive()。想知道这两个API是干什么的?一起接着往下看。
『isReactive()』
『定义』
【官方解释】
检查一个对象是否是由 reactive()
或 shallowReactive()
创建的代理。
【我的理解】
isReactive()
用于检查对象是否是由reactive创建的响应式代理。
『用法』
isReactive()
是用来检测reactive
类型的,如果是返回的是true,否则返回false。
『注意』
- 如果该代理是
readonly()创建的,但包裹了由reactive创建的另一个代理,它也会返回true。
『示例?』
<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源码如下⬇️:
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源码如下⬇️:
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的属性都不会被代理自动解包。
『用法』
import { shallowReactive} from 'vue'
setup(){
let person = shallowReactive({
//只考虑第一层数据的响应式
name:'wnxx',
address:{
provice: '云南省',
city: '丽江市'
}
})
}
『注意』
- ⚠️谨慎使用
浅层数据结构应该只用于组件中的根级状态。请避免将其嵌套在深层次的响应式对象中,因为它创建的树具有不一致的响应行为,这可能很难理解和调试。
- 对象数据中的,浅层和深层数据都要做处理时,一定要慎用!!!
shallowReactive()
通常是,当我们需要创建一个响应式对象,但是不希望其嵌套属性也响应式更新时,可以使用这个API。
『示例?』
使用shallowReactive
创建一个响应式对象infoData
,其中包含几个直接属性name
等等和两个嵌套属性address
和hobby
。然后对数据进行修改,添加操作,观察视图的变化情况。
<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.provice
和infoData.address.city
属性时,地址属性控制台打印信息显示已完成更新操作,视图上未发生变化,不会触发响应式更新。
之所以会是这种效果就是因为shallowReactive
是浅层作用形式。对于修改,添加直接属性是会触发更新,嵌套属性是不会触发更新的。
如果我们想要响应式更新嵌套属性,需要使用reactive
或者ref
来创建响应式对象。
『shallowReactive源码』
shallowReactive源码如下⬇️:
export function shallowReactive<T extends object>(
target: T
): ShallowReactive<T> {
return createReactiveObject(
target,
false,
shallowReactiveHandlers,
shallowCollectionHandlers,
shallowReactiveMap
)
}
『参数说明』:
- 第一个参数还是target。
- 第二个是isReadonly,为false。
- 第三个参数shallowReactiveHandlers是shallowReactive对应的处理函数。
- 第四个参数是对于集合类型的对象进行处理的shallowReactive所对应的函数。
内部调用了createReactiveObject函数。