其它Composition API 3.x
vue3.x shallowReactive 与shallowRef
shallowReactive:只处理对象最外层属性的响应式(浅响应式)。
shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。
什么时候使用?
如果有一个对象数据,结构比较深,但变化时只是外层属性变化===> shallowReactive。
如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换===> shallowRef,
<template>
<h2>x的值为{{x}}</h2>
<button @click="x++">x的值++</button>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<hr/>
<h2>涨薪:{{job.java.salary}}</h2>
<button @click="job.java.salary++">涨薪</button>
</template>
<script>
import {toRef,reactive,toRefs,shallowReactive,shallowRef} from "vue"
export default {
name: 'Dome',
setup(){
//let person = shallowReactive({//只考虑第一层数据的响应式
let ponsen=reactive({
name:"张三",
age:18,
job:{
java:{
salary:20
}
}
})
let x=shallowRef(0);//只能处理基本的数据类型,不能处理对象的数据类型
return{
...toRefs(ponsen),
x
}
}
}
</script>
vue3.x readonly 与 shallowReadonly
readonly:让一个响应式数据变为只读的(深只读)。
shallowReadonly:让一个响应式数据变为只读的(浅只读)。
应用场景:不希望数据被修改时。
<template>
<h2>x的值为{{sum}}</h2>
<button @click="sum++">x的值++</button>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<hr/>
<h2>涨薪:{{job.java.salary}}</h2>
<button @click="job.java.salary++">涨薪</button>
</template>
<script>
import {reactive,toRefs, ref,readonly,shallowReadonly} from "vue"
export default {
name: 'Dome',
setup(){
let sum=ref(0);
let ponsen=reactive({
name:"张三",
age:18,
job:{
java:{
salary:20
}
}
})
//ponsen=readonly(ponsen)//不能修改ponsen的数据
ponsen=shallowReadonly(ponsen)//不能修改ponsen的数据,只限第一层,薪资照样可以修改
//sum=readonly(sum)
//sum=shallowReadonly(sum)
return{
...toRefs(ponsen),
sum
}
}
}
</script>
vue3.x toRaw与markRaw
toRaw:
作用:将一个由reactive生成的响应式对象转为普通对象。
使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
markRaw:
作用:标记一个对象,使其永远不会再成为响应式对象。
应用场景:
-
有些值不应被设置为响应式的。例如复杂的第三方类库等。
-
当渲染具有不可变数据源的大列表时。跳过响应式转换可以提高性能。
Dome.vue
<template>
<h2>x的值为{{sum}}</h2>
<button @click="sum++">x的值++</button>
<h2>姓名:{{name}}</h2>
<h2>年龄:{{age}}</h2>
<h2 v-show="ponsen.car">汽车{{ponsen.car}}</h2>
<button @click="name+='~'">修改姓名</button>
<button @click="age++">增长年龄</button>
<hr/>
<h2>涨薪:{{job.java.salary}}</h2>
<button @click="job.java.salary++">涨薪</button>
<button @click="showRawPonsen">输出最原始的数据</button>
<button @click="addCar">添加一台车</button>
<button @click="ponsen.car.name+='!'">修改车名</button><!--无法修改车名,不在是响应式-->
<button @click="changePrice">修改车价格</button>
</template>
<script>
import {reactive,toRefs, ref,toRaw,markRaw} from "vue"
export default {
name: 'Dome',
setup(){
let sum=ref(0);
let ponsen=reactive({
name:"张三",
age:18,
job:{
java:{
salary:20
}
}
})
//将一个由reactive生成的响应式对象转为普通对象。
function showRawPonsen(){
const p=toRaw(ponsen);
console.log(p)
}
//标记一个对象,使其永远不会再成为响应式对象。不会修改值
function addCar(){
let car={name:"奔驰",price:40}
ponsen.car=markRaw(car);
}
//修改价格
function changePrice(){
let price=ponsen.car.price++
console.log(price)
}
return{
...toRefs(ponsen),
sum,
ponsen,
showRawPonsen,
addCar,
changePrice
}
}
}
</script>
vue3.x customRef
作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
Dome.vue
<template>
<input type="text" v-model="keyWord">
<h3>{{keyWord}}</h3>
</template>
<script>
import {customRef} from "vue"
export default {
name: 'Dome',
setup(){
//自定义一个ref名为:myRef
function myRef(value,delay){
return customRef((track,trigger)=>{
let timer
return{
get(){
console.log("有人读取了"+value+"的值")
track()//通知Vue追踪value的变化(提前和get商量一下,让他认为这个value是有用的)
return value;
},
set(newValue){
console.log("有人修改了"+newValue+"的值")
value=newValue
clearTimeout(timer)//清空时间
timer=setTimeout(()=>{
value=newValue
trigger()//让vue重新解析模板
},delay)//delay指定时间
}
}
})
}
//let keyWord=ref('hello')//使用vue提供的ref
let keyWord=myRef('hello',500)//使用自定义的ref
return{
keyWord
}
}
}
</script>
vue3.x provide 和 inject 函数

作用:实现祖孙组件间通信
套路:父组件有一个provide选项来提供数据,子组件有一个inject选项来开始使用这些数据
测试
父组件
<template>
<div class='app'>
我是祖组件(祖){{name}}--{{price}}
<Child/>
</div>
</template>
<script>
import Child from "./components/Child.vue"
import {reactive,toRefs,provide} from "vue"
export default {
name: 'App',
components: {Child},
setup(){
let car=reactive({name:"奔驰",price:"40w"})
provide("car",car)//给自己的后代组件传递数据
return{
...toRefs(car)
}
}
}
</script>
<style>
.app{
background: rebeccapurple;
padding: 10px;
}
</style>
子组件
<template>
<div class='child'>
我是Child组件{{car.name}}--{{car.price}}
<Son/>
</div>
</template>
<script>
import Son from "./Son.vue"
import {inject} from "vue"
export default {
name: 'Child',
components: { Son },
setup(){
let car=inject('car')//获取父组件传的值
console.log(car)
return{car}
}
}
</script>
<style>
.child{
background: blue;
padding: 10px;
}
</style>
子组件
<template>
<div class='son'>
我是Son组件{{car}}
</div>
</template>
<script>
import {inject} from "vue"
export default {
name: 'Son',
setup(){
const car=inject('car')//获取祖组件传的值
console.log(car)
return{car}
}
}
</script>
<style>
.son{
background: greenyellow;
padding: 10px;
}
</style>
响应式数据的判断
isRef:检查一个值是否为一个ref对象
isReactive:检查一个对象是否是由reactive创建的响应式代理
isReadonly:检查一个对象是否是由readonly创建的只读代理
isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理
测试
<template>
<div class='app'>
</div>
</template>
<script>
import {ref,reactive,toRefs,provide,isRef,isReactive,isReadonly,isProxy, readonly} from "vue"
export default {
name: 'App',
components: {},
setup(){
let car=reactive({name:"张三",age:"李四"})
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))
}
}
</script>