## 1.shallowReactive与shallowRef
* shallowReactive:只处理对象最外层属性的响应式(浅响应式)只考虑第一层数据的响应式。
* shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理,传递基本数据类型的话跟ref没有任何区别,ref是可以进行对象的响应式处理的
**我们正常的ref创建的数据,里面的.value是一个proxy,而shallowRef创建的数据 .value里面是一个object数据类型,所以不会响应式数据**
* 什么时候使用?:
* 如果有一个对象数据,结构比较深,但变化时只是外层属性变化 ===> shallowReactive
* 如果有一个对象数据,后续功能不会修改对象中的属性,而是生新的对象来替换 ===> shallowRef
## 2.readonly与shallowReadonly
* readonly:让一个响应式的数据变成只读的(深只读)
* shallowReadonly: 让一个响应式数据变成只读的(浅只读)
* 应用场景:不希望数据被修改的时候
```
<script>
import { reactive,readonly,shallowReadonly } from 'vue'
export default {
name: 'test9',
setup(){
let person = reactive({
name: '张三',
job:{
salary: '20k',
}
})
person = readonly(person) //这个时候修改人的信息就不会改变了,所有的都不能改
/**
* 页面不进行响应式的改变,一般存在两种情况:
* 1.setup里面定义的数据改变了,但是vue没有检测到,这个时候是不会改变的
* 2.setup里面定义的数据压根儿就不让你改,这个时候也没法响应式
*/
person = shallowReadonly(person) //只有最外层不能修改是只读的,但是job还是可以改的
return {
person
}
},
}
</script>
```
## 3.toRaw与markRaw
toRaw
作用:将一个由reactive生成的响应式对象转换为普通对象
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新
markRow:
作用:标记一个对象,使其永远不会再成为响应式对象
使用场景:
1.有些值不应被设置成响应式的,例如复杂的第三方类库等
2.当渲染具有不可变数据的大列表时候,跳过响应式转换可以提高性能
```
import {reactive,toRaw,markRaw} from 'vue'
setup(){
let person = reactive({
name: '张三',
})
function showRawPerson(){
const p = toRaw(person)
p.age++
console.log(p)
}
function addCar(){
let car = {name: '奔驰'}
person.car = markRaw(car) //一旦这么做时候,他就永远不能当成响应式数据去做了
}
}
```
## 4.customRef
* 创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制
* 实现防抖效果:
```
<template>
<input type="text" v-model="keyword">
<h3>{{keyword}}</h3>
</template>
<script>
import { customRef, ref } from 'vue'
export default {
name: 'test10',
setup(){
let timer;
//自定义一个ref——名为: myRef
function myRef(value){
return customRef((track,trigger)=>{
return {
get(){
console.log(`有人读取我的值了,要把${value}给他`); //两次输出: v-model读取 h3里面的插值语法调了一次
track() //追踪一下改变的数据(提前跟get商量一下,让他认为是有用的)
return value
},
set(newValue){
console.log(`有人把myRef这个容器中数据改了:${newValue}`);
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //通知vue去重新解析模板,重新再一次调用get()
},500)
}
}
})
}
// let keyword = ref('hello') //使用内置提供的ref
let keyword = myRef('hello') //使用自定义的ref
return {
keyword,
}
},
}
</script>
```
## 5.provide与inject:依赖注入
* 作用:实现祖孙组件间的通信
* 套路:父组件有一个provide选项提供数据,子组件有一个inject选项来开始使用这些数据
* 具体写法:
```
//父组件
<script setup>
import { ref,reactive,toRefs,provide } from 'vue';
import ChildVue from './components/Child.vue';
let car = reactive({
name: '奔驰',
price: '40w'
})
provide('car',car) //给自己的后代组件传递数据
const {name, price} = toRefs(car)
</script>
<template>
<div class="app">
<h3>我是父组件, {{name}}--{{price}}</h3>
<ChildVue></ChildVue>
</div>
</template>
```
```
//子组件
<script setup>
import { ref } from '@vue/reactivity';
import SonVue from './Son.vue';
</script>
<template>
<div class="app2">
<h3>我是子组件</h3>
<SonVue></SonVue>
</div>
</template>
```
```
//孙组件
<script setup>
import { ref,inject } from 'vue';
let car = inject('car') //拿到父组件的数据
const {name, price} = car
</script>
<template>
<div class="app3">
<h3>我是孙组件</h3>
<p>{{name}}-{{price}}</p>
</div>
</template>
```
## 6.响应式数据的判断
isRef:检查一个值是否为ref对象
isReactivce:检查一个对象是否是由reactive创建的响应式代理
isReadonly:检查一个对象是否由readonly创建的只读代理
isProxy:检查一个对象是否由reactive或者readonly方法创建的代理