《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly

文章目录

  • ​​三、其它 Composition API(不常用,了解即可)​​
  • ​​1.shallowReactive 与 shallowRef​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​2.readonly 与 shallowReadonly​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​3.toRaw 与 markRaw​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​4.customRef​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​5.provide 与 inject​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​6.响应式数据的判断​​
  • ​​测试案例​​
  • ​​完整代码​​
  • ​​本人其他相关文章链接​​

三、其它 Composition API(不常用,了解即可)

1.shallowReactive 与 shallowRef

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_02


注意点1:

问题:为啥shallowRef包裹的对象类型数据,不是响应式的?

答案:案例模拟如下
数据准备:

let x = shallowRef({
y:0
})
console.log('******',x)
-----------------------------------------------------------------------------------------------------------
let x = ref({
y:0
})
console.log('******',x)

针对ref包裹的对象类型数据,结果打印是Proxy,所以是响应式的

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_03

针对shallowRef包裹的对象类型数据,结果打印是Object,所以肯定不是响应式的

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_04

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_05

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
<Demo v-if="isShowDemo"/>
</template>

<script>
import {ref} from 'vue'
import Demo from './components/Demo'
export default {
name: 'App',
components:{Demo},
setup() {
let isShowDemo = ref(true)
return {isShowDemo}
}
}
</script>

Demo.vue

<template>
<h4>当前的x.y值是:{{x.y}}</h4>
<button @click="x={y:888}">点我替换x</button>
<button @click="x.y++">点我x.y++</button>
<hr>
<h4>{{person}}</h4>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>薪资:{{job.j1.salary}}K</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
</template>

<script>
import {ref,reactive,toRef,toRefs,shallowReactive,shallowRef} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let person = shallowReactive({ //只考虑第一层数据的响应式
// let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})
let x = shallowRef({
y:0
})
console.log('******',x)

//返回一个对象(常用)
return {
x,
person,
...toRefs(person)
}
}
}
</script>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly_06

2.readonly 与 shallowReadonly

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_07


注意点1:

如果使用readonly包裹的person对象的所有属性数据都只读不可需改,即name、age、salary都只读无法修改。

如果使用shallowReadonly包裹的person对象的所有属性数据,其中浅层次的设为只读,即name、age只读无法修改,但是salary可读可修改,因为salary是深层次的,不受管控。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_08

注意点2:

针对注意点1,使用readonly和shallowReadonly函数修饰后哪怕你修改属性了,控制台也会报错拦截,如图

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_09


注意点3:

问题:既然定义了person响应式数据,那就希望被修改,但你readonly和shallowReadonly函数又不希望被修改,总感觉这两函数是不是很多余,很奇怪,啥场景才使用它?

答案:万一这个person的数据是别的组件定义传给你的,别的组件传给你只希望你使用不希望你修改的情况下,你怕自己组件内业务逻辑可能会修改它,所以用readonly和shallowReadonly函数去修饰,然后用readonly(person)包裹后新生成的person对象就可以达到效果了,哪怕你修改新生成person对象属性,也不会影响原有的person对象的属性。

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_05

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
<Demo v-if="isShowDemo"/>
</template>

<script>
import {ref} from 'vue'
import Demo from './components/Demo'
export default {
name: 'App',
components:{Demo},
setup() {
let isShowDemo = ref(true)
return {isShowDemo}
}
}
</script>

Demo.vue

<template>
<h4>当前求和为:{{sum}}</h4>
<button @click="sum++">点我++</button>
<hr>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>薪资:{{job.j1.salary}}K</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
</template>

<script>
import {ref,reactive,toRefs,readonly,shallowReadonly} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let sum = ref(0)
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})

person = readonly(person)
// person = shallowReadonly(person)
// sum = readonly(sum)
// sum = shallowReadonly(sum)

//返回一个对象(常用)
return {
sum,
...toRefs(person)
}
}
}
</script>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_11

3.toRaw 与 markRaw

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly_12


注意点1:

之前上面讲解的函数都是把普通数据 -> 响应式数据,如图红线1,但是有时我们也需要把响应式数据 -> 普通数据,如图绿线2

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_13

注意点2:

问题:如图,我先用toRaw(person)把响应式person对象转为p普通对象,然后一顿修改p的age属性,那么页面会更新值吗?

答案:不会,因为p的对象类型为Object,它不是一个响应式的,所以修改无效。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_14

结果展示如图:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_15

注意点3:

toRaw函数只处理reactive缔造的响应式数据有效,针对ref缔造的响应式数据无效,比如代码如图1,点击按钮“输出最原始的person”,打印ref缔造的响应式数据结果如图2,打印reactive缔造的响应式数据结果如图3。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly_16

如图1

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_17

如图2

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_18

如图3

注意点4:

问题:假设我给person新增个car属性,代码如下,但是报错了为啥?,报错如图1

<h3>座驾信息:{{car}}</h3>
<button @click="addCar">给人添加一台车</button>

function addCar(){
let car = {name:'奔驰',price:40}
person.car = car
}

//返回一个对象(常用)
return {
sum,
...toRefs(person),
showRawPerson,
addCar
}

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_19

如图1

答案:你执行到…toRefs(person)的时候,addCar按钮和方法还没执行呢,也就是初始化时person里面还没有car属性呢,你项目启动后模板渲染后肯定报错啊,报错说car没定义在实例上。但是哪怕…toRefs(person)执行后你再往person对象新增个car属性,…toRefs(person)也不会再执行一遍,因为如果…toRefs(person)想再执行一遍,除非setup()再执行一遍,但很可惜整个项目启动后setup()只会执行一遍。

解决方案是:有2种解决办法:

  • 办法1:在定义person对象时,先定义一个空的car属性用来占位
  • 办法2:在return返回对象中,在…toRefs(person)的上面提前返回个person对象,同时修改<h3>标签体内容即可。


    原理是:在…toRefs(person)的上面提前返回个person对象,就会把整个person响应式对象交出去,这个person响应式对象中任何属性发生变化都能被vue监测到。

注意点5:

问题:针对注意点4中代码,为啥定义person.car = car,也行实现person中car属性的的响应式?car不是定义普通的Object类型的对象吗?

function addCar(){
let car = {name:'奔驰',price:40}
person.car = car
}

//返回一个对象(常用)
return {
sum,
person,
...toRefs(person),
showRawPerson,
addCar
}

答案:因为return配置了返回person,就相当于配置了Proxy代理,只要捕获到对person任何属性的操作,任何属性的操作都是响应式的。

注意点6:

person.car = markRaw(car),使用markRaw函数,可以使person中car属性无法进行修改,案例效果如图:toRaw与markRwa-注意点6-结果展示.gif,需要说明的是:car内部属性值已经改了,只是没有响应式更新而已,它和readonly不同,readonly是压根不让修改。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_20

toRaw与markRwa-注意点6-结果展示.gif

注意点7:

问题:何时使用markRaw?

答案:

  • 场景1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
  • 场景2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。

注意点8:

问题:针对注意点7中场景1,如何理解使用复杂的第三方类库时最好使用markRaw函数标记?

答案:如图,假设person中axios这个是第三方类库提供的超级复杂至少二三十层嵌套的数据,当你return配置返回person对象时,那么第三方类库提供的超级复杂的axios数据中,所有的属性都会做proxy代理做响应式,明显会超级浪费资源且效率太低,所以需要用markRaw进行标记为只读不可修改,这样vue监测到就不会把axios数据中所有的属性都会做proxy代理做响应式,从而达到节省了资源消耗的目的,且解决效率太低的问题。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_21

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_05

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<button @click="isShowDemo = !isShowDemo">切换隐藏/显示</button>
<Demo v-if="isShowDemo"/>
</template>

<script>
import {ref} from 'vue'
import Demo from './components/Demo'
export default {
name: 'App',
components:{Demo},
setup() {
let isShowDemo = ref(true)
return {isShowDemo}
}
}
</script>

Demo.vue

<template>
<h4>当前求和为:{{sum}}</h4>
<button @click="sum++">点我++</button>
<hr>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2>薪资:{{job.j1.salary}}K</h2>
<h3 v-show="person.car">座驾信息:{{person.car}}</h3>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<button @click="job.j1.salary++">涨薪</button>
<button @click="showRawPerson">输出最原始的person</button>
<button @click="addCar">给人添加一台车</button>
<button @click="person.car.name+='!'">换车名</button>
<button @click="changePrice">换价格</button>
</template>

<script>
import {ref,reactive,toRefs,toRaw,markRaw} from 'vue'
export default {
name: 'Demo',
setup(){
//数据
let sum = ref(0)
let person = reactive({
name:'张三',
age:18,
job:{
j1:{
salary:20
}
}
})

function showRawPerson(){
const p = toRaw(person)
p.age++
console.log(p)
}

function addCar(){
let car = {name:'奔驰',price:40}
person.car = markRaw(car)
}

function changePrice(){
person.car.price++
console.log(person.car.price)
}

//返回一个对象(常用)
return {
sum,
person,
...toRefs(person),
showRawPerson,
addCar,
changePrice
}
}
}
</script>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_23

4.customRef

  • 作用:创建一个自定义的 ref,并对其依赖项跟踪和更新触发进行显式控制。
  • 实现防抖效果:所谓防抖效果指的是我输入框输入值停了,下方的显示才会实现更新修改,具体错误演示请看注意点7
<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>

注意点1:

问题:如图中,两个return分别指代什么?

答案:第1个return指代“把你自定义的ref函数交出去”,而第2个return指代“vue语法要求,其中customeRef形参中的返回体必须返回一个对象,所以必须写return{}”

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_24

注意点2:

问题:绿色框中的get和set方法何时被调用?

答案:绿色框为自定义ref函数,红色框为调用方,当红色框进行调用并传入hello参数给绿色框时,绿色框就相当于一个大盒子(或者叫“中转站容器”),当模板<h3>和输入框<input>从绿色大盒子读取数据时,get就被调用了,当想修改绿色框大盒子中的属性值时,set就被调用了。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_25

注意点3:

问题:如下如图代码为啥打印了2次?

答案:因为模板<h3>和输入框<input>各读取了一次keyWord属性

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_26


《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_27

注意点4:

问题:想实现修改功能,为啥要写红框的代码?

答案:先说明下,myRef(value)中的形参value代表调用自定义函数传入的参数,而set(newValue)中的newValue代表输入框修改后的值,那get方法返回的value指代你传入的参数是啥,我就原封不动的返回出去。

问题:那为什么需要设置value = newValue才能实现<input>输入值后,<h3>标签就响应式更新值呢?

答案:就在get方法的返回值那里,因为get返回了初始化传入的value属性值,而你后续如果想实现修改,那么必须把修改后的newValue值赋值给value才行,才能实现<input>修改值后,<h3>标签值也跟着响应式更新,否则无论<input>如何修改值,<h3>标签值压根不会改动。

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_28

注意点5:

问题:针对注意点4红框中,为啥要设置trigger(),trigger作用是啥?

答案:设置value = newValue是把get要返回的value值给改了,但是你不通知它再重新触发一次解析模板操作,那么get()方法人家不会再调用一次啊 (大白话讲:value已经改了,但你得重新触发一次解析模板操作,这样修改后的值才能呈现在<h3>标签体中,否则页面值还是无法修改),图中代表调用set方法后应该执行的顺序

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_29


注意点6:

问题:针对注意点4中红框中设置track(),track作用是啥?

答案:自定义ref函数中的get方法返回的value,它很矫情,不是你通过set方法修改了value值它就会返回最新值给页面,它生效的前提是必须设置track(), 这个track就相当于通知vue追踪数据的变化,只要你返回 return value之前,调用track()进行通知追踪就会生效,就能实现<input>修改值后,<h3>标签值也跟着响应式更新,如果不写track()这句,页面还是不会响应式更新的。

注意点7:
需要把案例改成防抖模式,当前的还是存在bug问题如图:customRef-注意点7-未加防抖效果-错误结果展示.gif,感觉一直输入内容而展示效果动不动就退一下,原因在于如图1,你定时器一直开着,就意味着相当于每次修改你都开一个定时器,而且当你输入频率比500毫秒块的时候就会把很多绿框的内容积压在一起,肯定会形成这个问题。而添加防抖修改过后的正确展示如图:customRef-注意点7-加了防抖效果-正确结果展示.gif,
修改地方为:

  • 第1步:先let timer应以一个定时器
  • 第2步:然后每次开定时器都把返回值交出去
  • 第3步:最后每次进定时器之前,都把已存在的定时器清掉
let timer
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //通知Vue去重新解析模板
},500)

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_30

customRef-注意点7-未加防抖效果-错误结果展示.gif

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_31

customRef-注意点7-加了防抖效果-正确结果展示.gif

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly_32

如图1

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_33

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<input type="text" v-model="keyWord">
<h3>{{keyWord}}</h3>
</template>

<script>
import {ref,customRef} from 'vue'
export default {
name: 'App',
setup() {
//自定义一个ref——名为:myRef
function myRef(value,delay){
let timer
return customRef((track,trigger)=>{
return {
get(){
console.log(`有人从myRef这个容器中读取数据了,我把${value}给他了`)
track() //通知Vue追踪value的变化(提前和get商量一下,让他认为这个value是有用的)
return value
},
set(newValue){
console.log(`有人把myRef这个容器中数据改为了:${newValue}`)
clearTimeout(timer)
timer = setTimeout(()=>{
value = newValue
trigger() //通知Vue去重新解析模板
},delay)
},
}
})
}

// let keyWord = ref('hello') //使用Vue提供的ref
let keyWord = myRef('hello',500) //使用程序员自定义的ref

return {keyWord}
}
}
</script>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReadonly_34

5.provide 与 inject

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_35

  • 作用:实现​​祖与后代组件​​间通信
  • 套路:父组件有一个 ​​provide​​​ 选项来提供数据,后代组件有一个 ​​inject​​ 选项来开始使用这些数据
  • 具体写法:

1.祖组件中:

setup(){
......
let car = reactive({name:'奔驰',price:'40万'})
provide('car',car)
......
}

2.后代组件中:

setup(props,context){
......
const car = inject('car')
return {car}
......
}

注意点1:
provide函数:用于给自己的后代组件传递参数
provide(‘car’,car),第1个参数为给你传入的参数起个名字,第2个参数为传入的参数。

inject函数:用于注入祖组件传递过来的参数
inject(‘car’),形参为传递过来的参数名字

注意点2:

const car = inject(‘car’)

其中inject注入的参数返回值也是个Proxy类型的对象,如图打印car

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_36

注意点3:
provide 与 inject函数 只能用在由“祖组件” -> “子组件”传递参数,不能由子组件 -> 祖组件,且祖组件传递给子组件的参数只能使用,子组件不能修改传递过来的值,否则报错。

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowRef_37

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<div class="app">
<h3>我是App组件(祖),{{name}}--{{price}}</h3>
<Child/>
</div>
</template>

<script>
import { reactive,toRefs,provide } from 'vue'
import Child from './components/Child.vue'
export default {
name:'App',
components:{Child},
setup(){
let car = reactive({name:'奔驰',price:'40W'})
provide('car',car) //给自己的后代组件传递数据
return {...toRefs(car)}
}
}
</script>

<style>
.app{
background-color: gray;
padding: 10px;
}
</style>

Child.vue

<template>
<div class="child">
<h3>我是Child组件(子)</h3>
<Son/>
</div>
</template>

<script>
import {inject} from 'vue'
import Son from './Son.vue'
export default {
name:'Child',
components:{Son},
/* setup(){
let x = inject('car')
console.log(x,'Child-----')
} */
}
</script>

<style>
.child{
background-color: skyblue;
padding: 10px;
}
</style>

Son.vue

<template>
<div class="son">
<h3>我是Son组件(孙),{{car.name}}--{{car.price}}</h3>
</div>
</template>

<script>
import {inject} from 'vue'
export default {
name:'Son',
setup(){
let car = inject('car')
return {car}
}
}
</script>

<style>
.son{
background-color: orange;
padding: 10px;
}
</style>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_vue3_38

6.响应式数据的判断

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_39

测试案例

完整代码

项目目录

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_readonly_33

main.js

//引入的不再是Vue构造函数了,引入的是一个名为createApp的工厂函数
import { createApp } from 'vue'
import App from './App.vue'

//创建应用实例对象——app(类似于之前Vue2中的vm,但app比vm更“轻”)
const app = createApp(App)

//挂载
app.mount('#app')

App.vue

<template>
<h3>我是App组件</h3>
</template>

<script>
import {ref, reactive,toRefs,readonly,isRef,isReactive,isReadonly,isProxy } from 'vue'
export default {
name:'App',
setup(){
let car = reactive({name:'奔驰',price:'40W'})
let sum = ref(0)
let car2 = readonly(car)

console.log(isRef(sum))
console.log(isReactive(car))
console.log(isReadonly(car2))
console.log(isProxy(car))
console.log(isProxy(sum))


return {...toRefs(car)}
}
}
</script>

<style>
.app{
background-color: gray;
padding: 10px;
}
</style>

结果展示:

《vue3第三章》其它 Composition API(不常用,了解即可),包括shallowReactive 与 shallowRef、readonly 与 shallowReadonly等等_shallowReactive_41