## 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方法創建的代理