首页技术栈归档照片墙音乐日记随想收藏夹友链留言关于

其它Composition API 3.x

写作时间:2026-07-08

其它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:

作用:标记一个对象,使其永远不会再成为响应式对象。

应用场景:

  1. 有些值不应被设置为响应式的。例如复杂的第三方类库等。

  2. 当渲染具有不可变数据源的大列表时。跳过响应式转换可以提高性能。

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>
avatar

yuanyourdomain

写代码,做研究,记录生活。

RECOMMENDED

MyBatis 动态 SQL

2026-07-08

Nginx 基础入门

2026-07-08

Maven 多模块与私服

2026-07-08