vue3x——shallowReactive和shallowRef、readonly和shallowReadonly、toRaw与markRaw、customRef
Vue3.x其他CompositionAPI1.shallowReactive和shallowRefshallowReactive:只处理对象最外层属性的响应式(浅层响应式)shallowRef:只处理基本数据类型响应式,不进行对象的响应式处理什么时候使用?:如果有一个对象数据,结构比较深,但变化时只是最外层属性变化===>shallowReactive如果有一个对象数据,后续功能
Vue3.x
其他CompositionAPI
1.shallowReactive和shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅层响应式)
shallowRef:只处理基本数据类型响应式,不进行对象的响应式处理
什么时候使用?:
如果有一个对象数据,结构比较深,但变化时只是最外层属性变化===>shallowReactive
如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替代====>shallowRef
<template>
<div>
<p>{{ obj }}</p>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>工作:{{ job.job1.name }}</p>
<p>薪资:{{ job.job1.salary }}K</p>
<button @click="name += '-'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="job.job1.salary++">加薪</button>
<hr />
<p>num的值:{{ num.y }}</p>
<button @click="num.y++">num+1</button>
</div>
</template>
<script>
// shallowReactive:浅层次的响应式,只响应第一层的数据,不能深层的响应
// shallowRef:不去处理对象数据类型的数据,不会形成响应式数据。ref处理对象类型的数据,底层还是求助reactive变成了proxy对象,从而形成响应式
import { reactive, toRefs, shallowReactive,shallowRef, ref } from "vue";
export default {
setup() {
// let obj = reactive({
let obj = shallowReactive({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
// let num = ref({y:0});//y值可修改,是响应式
let num = shallowRef({y:0});//y值只能显示,不处理对象类型的数据
return {
obj,
...toRefs(obj),
num,
};
},
};
</script>
<style>
</style>
2.readonly和shallowReadonly
readonly:让一个响应式数据变为只读的(深只读,全部属性都是只读)
shallowReadonly:让一个响应式数据变为只读(浅只读,第一层属性只读,其余层属性可读写)
应用场景:不希望数据被修改时
<template>
<div>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>工作:{{ job.job1.name }}</p>
<p>薪资:{{ job.job1.salary }}K</p>
<button @click="name += '-'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="job.job1.salary++">加薪</button>
<hr />
<p>num的值:{{ num }}</p>
<button @click="num++">num+1</button>
</div>
</template>
<script>
import { reactive, toRefs, ref,readonly,shallowReadonly } from "vue";
export default {
setup() {
let obj = reactive({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
let num=ref(0);
// 接收一个响应式数据,加工后返回一个数据,里面的数据都不可以修改,
// 原先的obj(可读写)被新的obj(只读)覆盖
// 使用场景:数据是别人定义的,你拿过来用,但是不能写,只能读,所以在拿过来之后,就用readonly处理加工返回一个只能读的数据
// obj = readonly(obj);
// 接收一个响应式数据,返回一个新的数据,该数据的第一层属性只能读,不能写,除了第一层,其余层次的属性都可读写
obj = shallowReadonly(obj);
return {
...toRefs(obj),
num,
};
},
};
</script>
<style>
</style>
使用ref和reactive定义数据,是为了将普通的数据(基本数据类型、引用数据类型)变成响应式的数据
3.toRaw与markRaw
toRaw:
作用:将一个由reactive生成的响应式对象转为普通对象
使用场景:用于读取响应式对象对应的普通对象,对这个普通的所有操作,不会引起页面的更新
markRaw:
作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:
1. 有些值不应该被设置为响应式的,例如复杂的第三方类库等
2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
<template>
<div>
<p>姓名:{{ name }}</p>
<p>年龄:{{ age }}</p>
<p>工作:{{ job.job1.name }}</p>
<p>薪资:{{ job.job1.salary }}K</p>
<button @click="name += '-'">修改姓名</button>
<button @click="age++">修改年龄</button>
<button @click="job.job1.salary++">加薪</button>
<hr />
<p>num的值:{{ num }}</p>
<button @click="num++">num+1</button>
<hr />
<!-- <p>原始的obj:{{ obj }}</p> -->
<button @click="showRawObj">显示原始的obj</button>
<hr />
<p v-show="obj.show">{{ obj.show }}</p>
<button @click="add">添加一个属性</button>
<button @click="obj.show.w++">w+</button>
<button @click="obj.show.h++">h+</button>
</div>
</template>
<script>
import { reactive, toRefs, ref, toRaw, markRaw } from "vue";
export default {
setup() {
let w = "";
let h = "";
// proxy对象
let obj = reactive({
name: "张三",
age: 22,
job: {
job1: {
name: "web工程师",
salary: 20,
},
},
});
// RefImpl对象
let num = ref(0);
function showRawObj() {
console.log(obj);
// 将proxy类型的obj,还原成原始Object类型
// toRaw只能转变reactive定义的数据
const p = toRaw(obj);
console.log(p);
}
function add() {
let newObj = { w: 46, h: 158 };
//在响应式对象身上添加任何属性,都是响应式的
<p>体重:{{w }}kg</p>
// obj.show = newObj;
// 标记newObj,使其不再是响应式
obj.show = markRaw(newObj);
console.log(obj);
}
// setup执行一次,就return一次,setup在beforeCreate之前执行一次
return {
num,
obj,
...toRefs(obj),
showRawObj,
add,
w,
h,
};
},
};
</script>
<style>
</style>
4.customRef
作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制
实现防抖效果:
<template>
<div>
<input type="text" v-model="keyWord" />
<h3>{{ keyWord }}</h3>
</div>
</template>
<script>
import { customRef, ref } from "vue";
export default {
name: "App",
setup() {
// 自定义ref
// 形参value是调用这个自定义ref传入的参数(旧值)
function myRef(value, delay) {
console.log(value);
// 是自定义的,所以要有自己写的逻辑,所以参数是一个回调函数
const keys = customRef((track, trigger) => {
let timer;
return {
// 读数据时调用
get() {
console.log("有人读取数据");
// 4.通知vue追踪数据(实参,value)的改变,
// 若是不用track追踪,get里面的value就一直是初始值
track();
// 3.解析模板,再次调用get,
return value;
},
// v-model绑定的数据改变了,就调用set(修改数据)
// 这个val是value改变后的值(新值)
set(val) {
// 调用set时,先清除掉上一个定时器
clearTimeout(timer);
console.log("有人修改数据了");
// 1.先改数据——value
// value = val;
// 2.通知vue重新解析模板
// trigger();
// 延迟解析模板
timer = setTimeout(() => {
value = val;
trigger();
}, delay);
},
};
});
return keys;
}
// let keyWord = ref("hello");//使用vue提供的ref(自动)
let keyWord = myRef("hello", 300); //手动
return {
keyWord,
};
},
};
</script>
<style>
</style>
更多推荐
所有评论(0)