这是我参与更文挑战的第26天,活动详情查看: 更文挑战
一、readonly与shallowReadonly
readonly深度只读数据,传入响应式或纯对象,返回一个原始对象的只读代理,对象内部任何嵌套的属性也是只读的,在某些特定的情况下,不希望对数据进行更新操作,那就可以包装生产一个只读代理对象来读取数据,防止对数据的修改或删除等操作。 shallowReadonly浅只读数据,传入响应式或纯对象,返回一个原始对象的只读代理,但是这个只读只是第一层只读,非深度只读。
下面代码中,使用readonly包裹的数据,深层都是只读的,shallowReadonly只有最外面那层才是只读的
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent, readonly, shallowReadonly } from "vue";
export default defineComponent({
name: "",
setup() {
// readonly 深层只读
let deepObj = readonly({
a: 0,
b: {
c: 0,
},
});
let changeDeepObj = () => {
deepObj.b.c++
}
// shallowReadonly 浅层只读
let shallowObj = shallowReadonly({
a: 0,
b: {
c: 0,
},
});
let changeShallowObj = () => {
shallowObj.b.c++
}
return {
deepObj,
changeDeepObj,
shallowObj,
changeShallowObj
}
},
});
</script>
<style scoped>
</style>
二、toRaw与markRaw
toRaw可以将由reactive或readonly函数转换成响应式代理的普通对象,对普通对象的属性值进行修改,就不会更新视图界面。一般用于渲染具有不可变数据源的大列表,跳过代理转换可以提高性能。
markRaw标记一个对象,使其永远不会转换为响应式数据,只能返回这个对象本身,一般用于某些值不该被设置为响应式的,比如第三方类实例或vue对象等场景。
下面代码,使用toRaw后,响应式的数据变为不是响应式了
<template>
<div>
<p>姓名: {{rawObjA.name}} 数量: {{rawObjA.count}} <button @click="changeRawObjA">改变rawObjA方法</button></p>
</div>
</template>
<script lang="ts">
import { defineComponent, toRaw, markRaw , reactive } from 'vue';
export default defineComponent({
name: 'raw',
setup() {
// 定义一个响应式数据
let reactiveObjA = {
name: '张三',
count: 1
}
// 使用toRaw转换响应式数据为不响应式数据
let rawObjA = toRaw(reactiveObjA)
// 改变rawObjA方法
let changeRawObjA = () => {
rawObjA.count++
console.log(rawObjA.count);
}
return {
rawObjA,
changeRawObjA
}
}
});
</script>
<style scoped>
</style>
markRaw标记一个永远不是响应式的数据, 哪怕后面用reactive转也是不响应式的
<p>姓名: {{markRawObjB.name}} 数量: {{markRawObjB.count}} <button @click="changeReactiveMarkRawB">改变rawObjA方法</button></p>
// 改变rawObjA方法
let changeRawObjA = () => {
rawObjA.count++
console.log(rawObjA.count);
}
// 2. markRaw 是标记一个数据永远是不响应式的
let markRawObjB = {
name: '王五',
count: 1
三、toRef的特点与作用
toRef为响应式对象上的某个属性创建一个Ref引用,更新时引用对象会同步更新,注意如果通过toRef创建的数据修改时,并不会触发视图界面的更新,因为toRef的本质是引用,与原始数据有关联。
从一个对象中拿出一个属性,操作这个属性,这个属性并不是响应式的
<template>
<div>
<p>{{objA.count}} <button @click="changeObjA">改变objA的方法</button> </p>
</div>
</template>
<script lang="ts">
import { defineComponent,toRef,reactive } from 'vue';
export default defineComponent({
name: '',
setup() {
let objA = reactive({
count: 0
})
let changeObjA = () => {
let count = objA.count
count++
}
return {
objA,
changeObjA
}
}
});
</script>
<style scoped>
</style>
使用toRef使其成为响应式
let count =toRef(objA,'count')
count.value++