Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解相关的知识,希望对你有一定的参考价值。


​​传送门:Vue3中 响应式 API ( reactive、ref、toRef、toRefs ) 详解​​传送门:Vue3中 响应式 API( shallowReactive、shallowRef、triggerRef 、customRef )详解

1. readonly 函数

接受一个对象 (不论是响应式还是普通的) 或是一个 ref,返回一个原值的只读代理。
只读代理是深层的:对任何嵌套属性的访问都将是只读的。它的 ref 解包行为与 reactive() 相同,但解包得到的值是只读的。
要避免深层级的转换行为,请使用 shallowReadonly() 作替代。

<template>
<div>
<div>
count
<button @click="changeCount">changeCount</button>
</div>
<div>
obj1.name obj1.info.age
<button @click="obj1Age">obj1Age</button>
</div>
</div>
</template>

<script>
import reactive,readonly, ref from vue;
export default
setup()
let count = ref(0);
let obj1 = reactive(
name:张三,
info:
age:18

)
count = readonly(count);
obj1 = readonly(obj1);

const changeCount = () =>
count.value++;
console.log(count)

const obj1Age = () =>
obj1.name = 李四;
obj1.info.age++;
console.log(obj1)

return
count,
changeCount,
obj1,
obj1Age,



</script>

分别触发 changeCount、obj1Age 一次

Vue3中

2. shallowReadonly 函数

readonly() 的浅层作用形式

和 readonly() 不同,这里没有深层级的转换:只有根层级的属性变为了只读。属性的值都会被原样存储和暴露,这也意味着值为 ref 的属性不会被自动解包了。

Vue3中

<template>
<div>
<div>
count
<button @click="changeCount">changeCount</button>
</div>
<div>
obj1.name obj1.info.age
<button @click="obj1Age">obj1Age</button>
</div>
</div>
</template>

<script>
import reactive,shallowReadonly, ref from vue;
export default
setup()
let count = ref(0);
let obj1 = reactive(
name:张三,
info:
age:18

)
count = shallowReadonly(count);
obj1 = shallowReadonly(obj1);

const changeCount = () =>
count.value++;
console.log(count)

const obj1Age = () =>
obj1.name = 李四;
obj1.info.age++;
console.log(obj1)

return
count,
changeCount,
obj1,
obj1Age,



</script>

分别触发 changeCount、obj1Age 一次

Vue3中

3. toRaw 函数

根据一个 Vue 创建的代理返回其原始对象。
toRaw() 可以返回由 reactive()、readonly()、shallowReactive() 或者 shallowReadonly() 创建的代理对应的原始对象。
这是一个可以用于临时读取而不引起代理访问/跟踪开销,或是写入而不触发更改的特殊方法。不建议保存对原始对象的持久引用,请谨慎使用。

<template>
<div>
<div>
obj.name obj.info.age
<button @click="objToRaw">objToRaw</button>
</div>
</div>
</template>

<script>
import reactive,toRaw from vue;
export default
setup()
let obj = reactive(
name:张三,
info:
age:18

)
const objToRaw = () =>
let objRaw = toRaw(obj)
objRaw.info.age++
console.log(obj,objRaw)

return
obj,
objToRaw,



</script>

触发 objToRaw 两次

Vue3中

4. markRaw 函数

将一个对象标记为不可被转为代理。返回该对象本身。
作用:标记一个对象,使其永远不会再成为响应式对象;
应用场景:

  • 有些值不应被设置为响应式的,如:复杂的第三方类库等;
  • 当渲染具有不可变数据源的大列表时,跳过响应式转换可提高性能;

Vue3中

<template>
<div>
<div>姓名:obj.name </div>
<div>年龄:obj.info.age </div>
<div v-if="obj.car">座驾:obj.car </div>
<div v-if="obj.address">地址:obj.address </div>
<button @click="updateObj">updateObj</button>
<button @click="changeAddress">changeAddress</button>
<button @click="changeCar">changeCar</button>
</div>
</template>

<script>
import reactive,markRaw from vue;
export default
setup()
let obj = reactive(
name:张三,
info:
age:18

)
const updateObj = () =>
const address = province:湖北,city:武汉 ;
obj.address = address; // obj 配置了 Proxy 代理,因此捕获到对 obj 任何属性的操作且都是响应式的;
const car = brand:宝马,price:30 ;
obj.car = markRaw(car); // car内部属性值已经改了,只是没有响应式更新。它和readonly不同,readonly是压根不让修改


function changeAddress()
obj.address.province = 江苏;
obj.address.city = 南京;
console.log(obj)


function changeCar()
obj.car.brand = BMW,
obj.car.price+= 1
console.log(obj)
;

return
obj,
updateObj,
changeCar,
changeAddress,



</script>

依次触发 updateObj、changeAddress、changeCar 一次,效果如下:

(若先触发 changeCar 再触发 changeAddress ,car 的页面信息会进行更新,因为 address 的改变带动了页面的更新 )

Vue3中


以上是关于Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解的主要内容,如果未能解决你的问题,请参考以下文章

Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解

Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解

Vue3中 响应式 API( shallowReactiveshallowReftriggerRef customRef )详解

Vue3中 响应式 API ( readonlyshallowReadonlytoRawmarkRaw ) 详解

Vue3.0源码剖析-响应式对象

shallowReadonly 与 readonly原理浅析