本文已参与「新人创作礼」活动,一起开启掘金创作之路。
前面讲过,vue3与vue2最大的改进就是 Composition API , 除了前面介绍的一些Composition API之外,还有很多其他的 Composition API,这一节我们就来看一看
- provide 与 inject
- shallowReactive 与 shallowRef
- readonly 与 shallowReadonly
- toRaw 与 markRaw
- customRef
1. provide 与 inject
vue2时祖与后代组件间,只能使用 bus和vuex来实现通信了,如果一层一层往下,那这就太麻烦了。vue3新增了 provide 与 inject 来实现祖与后代组件间的通信,非常的方便操作
-
父组件有一个
provide选项来提供数据,后代组件有一个inject选项来开始使用这些数据 -
示例
- 祖先
setup(){ let car = reactive({name:'奔驰',price:'40万'}) provide('car',car) }- 子孙
setup(props,context){ const car = inject('car') return {car} }
这样是不是太方便了,简化了我们的操作
2. shallowReactive 与 shallowRef
在上一节学习reactive和ref的时候讲过他们是为递归监听,本质是Proxy只能监听到当前对象下属性的变化,当属性为引用数据类型时,属性的属性他是监听不到的,所以需要递归监听
那当在项目中数据过于复杂并且我们没有这种递归监听的需求时,这样的操作是很消耗性能的,所以vue3提供了非递归监听的API:shallowReactive和shallowRef,只监听第一层数据的变化
-
作用场景
- 如果有一个对象数据,结构比较深, 但变化时只是外层属性变化 ===> shallowReactive
- 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef
-
shallowReactive:只处理对象最外层属性的响应式(浅响应式)
-
shallowRef:只处理基本数据类型的响应式, 不进行对象的响应式处理
3. readonly 与 shallowReadonly
- 作用场景: 当你希望数据被不能被修改时,可以使用他们
- readonly: 让一个响应式数据变为只读的(深只读)。
- shallowReadonly:让一个响应式数据变为只读的(浅只读)。
const定义的变量也是不能改的,那readonly和const有什么区别?
- const是赋值保护,使⽤const定义的变量,该变量不能重新赋值。如果const赋值的是对象,那么对象⾥⾯的东西是可以改的。原因是const定义的变量不能改说的是,对象对应的那个地址不能改变,而不是里面的值不能修改
- readonly是属性保护,不能给属性重新赋值,值是不能变的
4. toRaw 与 markRaw
- toRaw:
- 作用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
- 作用:将一个由
reactive生成的响应式对象转为普通对象,与代理数据指向相同的引用地址,与源数据无关
import { reactive, toRaw} from 'vue'
setup() {
let obj = {name:'lsh',age:18};
let state = reactive(obj)
let obj2 = toRaw(state)
console.log(obj === obj2) //true
}
- markRaw:
- 作用场景:
- 有些值不应被设置为响应式的,例如复杂的第三方类库等。
- 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
- 作用:标记一个对象,使其永远不会再成为响应式对象,即源对象本身就不需要响应式
- 作用场景:
import { reactive,markRaw } from 'vue'
let obj = {name:'lsh',age:18};
obj = markRaw(obj)
let state = reactive(obj)
5. customRef
- 作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制
- 可以使用他来实现一个防抖的效果,下面看下一代码
<template>
<input type="text" v-model="keyword">
<h3>{{keyword}}</h3>
</template>
<script>
import {ref,customRef} from 'vue'
export default {
name:'Demo',
setup(){
// let keyword = ref('hello') //使用Vue准备好的内置ref
//自定义一个myRef
function myRef(value,delay){
let timer
//通过customRef去实现自定义
return customRef((track,trigger)=>{
return{
get(){
track() //告诉Vue这个value值是需要被“追踪”的
return value
},
set(newValue){
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //告诉Vue去更新界面
},delay)
}
}
})
}
let keyword = myRef('hello',500) //使用程序员自定义的ref
return {
keyword
}
}
}
</script>