除了之前的 ref与reactive 之外,Vue3 还准备了另外两个API,也是用来对响应式数据做处理,那就是 shallowReactive 与 shallowRef
shallowReactive
文档解释:reactive() 的浅层作用形式,只能定义对象类型的数据。和 reactive()
不同,这里没有深层级的转换:一个浅层响应式对象里只有根级别的属性是响应式的。属性的值会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。
也就是说,shallowReactive 定义的响应式数据,只有第一层数据是响应式的,嵌套的数据则不会被转化为响应式。
<template><button @click="person.age++">年龄+1</button><button @click="person.job.j1.salary++">薪资+1</button><button @click="person.arr[0]++">arr数组第一个值+1</button><p>{{ person }}</p>
</template>let person = shallowReactive({name: "al",age: 28,job: {j1: {work: "前端",salary: 2,},},arr:[1,2,3]
});
经过测试发现,只有 age 发生了改变,嵌套的数据 job 以及 数组 arr 都没有改变。这就说明了只有第一层数据,且第一层数据的值为简单类型时才会被转化成响应式。若值为对象或数组等复杂类型,则不会被转化为响应式。
但是我们还是可以 通过 替换 的方式来改变 job 或 arr 等复杂类型数据
<template><button @click="person.job = {msg:'job被改变了'}">job被替换了</button><button @click="person.arr = [4,5,6]">arr被替换了</button><p>{{ person }}</p>
</template>
shallowRef
文档解释:ref() 的浅层作用形式。和 ref()
不同,浅层 ref 的内部值将会原样存储和暴露,并且不会被深层递归地转为响应式。只有对 .value
的访问是响应式的。
首先 ref 是可以接收基础类型数据和对象类型数据的,shallowRef 也能接收同样类型的数据,但是 shallowRef 只会对基础类型数据进行转化,对于复杂类型则不会被转化为响应式。
还是上面的例子,我们通过 shallowRef 来转化,先打印一下转化后的person对象
person 还是一个ref 对象,但是其中的 value 已经不是Proxy代理对象了,而是一个普通对象,也就是说 shallowRef 无法将对象转化为响应式数据。
验证一下:
我们依次点击按钮,发现数据完全没有发生改变,这就证明了 shallowRef 无法将对象转化为响应式数据。
既然 shallowRef 无法将对象转化为响应式数据。那么 对于普通类型的数据 shallowRef 会怎么处理呢?
<template><button @click="sum++">sum+1</button><p>{{ sum }}</p>
</template>let sum = shallowRef(0)
打印一下 sum ,我们发现 sum是一个 ref 对象,其中的 value 则是响应式数据
经过测试 sum 确实真的是响应式数据
说明 shallowRef 是能将基础类型数据转化为响应式的。
总结
- shallowReactive:只处理对象最外层属性的响应式(浅响应式)
- shallowReactive 中说 属性的值会被原样存储和暴露:Vue 只会对对象的顶层属性进行响应式处理,嵌套在内部的对象或数组保持原始状态,不会被转化为响应式。当访问或修改这些嵌套属性时,Vue 不会跟踪这些变化,也不会触发响应式更新
- 原样存储:当你使用
shallowReactive
创建一个浅层响应式对象时,Vue 只会对这个对象的顶层属性进行响应式处理,数组或嵌套在内部的对象将不会被自动转换为响应式对象。Vue 不会递归地深入处理嵌套属性,这些嵌套属性保留为原始的(未处理过的)非响应式数据。 -
原样暴露:在访问
shallowReactive
对象时,顶层属性是响应式的,你可以直接访问它们,且修改这些属性会触发 Vue 的响应式更新机制。但当你访问或修改嵌套属性时,这些嵌套属性依旧是原始的非响应式数据,Vue 不会跟踪它们的变化。
- 原样存储:当你使用
- shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理
- shallowRef 说 内部值将会原样存储和暴露:
shallowRef
对象中的值不会被 Vue 的响应式系统处理为响应式的嵌套对象,而是直接存储并在访问时原样提供。仅顶层的对象引用会受到响应式系统的追踪,而嵌套的属性或对象则不会,- 原样存储:
shallowRef
内部存储的值是原始的、未经过任何响应式处理的。这意味着当你把一个对象传递给shallowRef
时,这个对象本身不会被转换为响应式对象,只有这个对象作为整体的引用会被响应式跟踪。 -
原样暴露:当你访问
shallowRef
的值时,你得到的仍然是这个原始的、未经过处理的对象。你可以直接访问和操作这个对象的属性,但这些属性的更改不会触发 Vue 的响应式系统。
- 原样存储:
-
使用情况:
-
shallowRef
性能优化:当你有一个非常复杂的对象结构,并且你只关心这个对象整体的变化,而不关心它内部细节的变化时,使用shallowRef
可以减少 Vue 的响应式开销。 -
第三方库集成:当你需要将 Vue 的响应式系统与某些外部库的对象(比如大型数据结构或库自带的对象)集成,而这些对象不需要深层次的响应式支持时,
shallowRef
是理想的选择。 -
shallowReactive
性能优化:当你只关心对象的顶层属性变化,而不需要深入嵌套属性的响应式支持时,shallowReactive
可以减少 Vue 的响应式处理开销。 -
处理复杂数据结构:当你处理的对象结构较为复杂(如嵌套很深或包含大量数据)且你希望避免 Vue 对整个数据结构进行递归响应式处理时,
shallowReactive
提供了对响应式控制的更大灵活性。
-