其他 Composition API、shallowReactive 与 shallowRef、 readonly 与 shallowReadonly【Vue3】】

三、其他 Composition API

1. shallowReactive 与 shallowRef

  • shallowReactive :只处理对象最外层属性的响应式(浅响应式)。
  • shallowRef:只处理基本数据类型的响应式,不进行对象的响应式处理。
  • 什么时候使用?
    • 如果有一个对象数据,结构比较深,但变化时只是外层属性变化 ===> shallowReactive。
    • 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替换 ===> shallowRef
<template>
  <h4>当前的x.y值是:{{ x.y }}</h4>
  <button @click="x.y ++">点我x+1</button>
  <hr>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}</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
    })

    

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

2. readonly 与 shallowReadonly

  • readonly:让一个响应式数据变为只读的(深只读)。
  • shallowReadonly:让一个响应式数据变为只读的(浅只读)。
  • 应用场景:不希望数据被修改时。
<template>
  <h4>当前求和为:{{ sum }}</h4>
  <button @click="sum++">点我++</button>
  <hr>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}</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>


3. toRow 与 markRow

  • toRow:
    • 作用:将一个由reactive生成的响应式对象转为普通对象
    • 使用场景:用于读取响应式对象对应的普通对象,对这个普通对象的所有操作,不会引起页面更新。
  • markRow:
    • 作用:标记一个对象,使其永远不会再成为响应式对象。
    • 应用场景:
      1. 有些值不应被设置为响应式的,例如复杂的第三方类库等。
      2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能。
<template>
  <h4>当前求和为:{{ sum }}</h4>
  <button @click="sum++">点我++</button>
  <hr>
  <h2>姓名:{{ name }}</h2>
  <h2>年龄:{{ age }}</h2>
  <h2>薪资:{{ job.j1.salary }}</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>


4. customRef

  • 作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制。
  • 实现防抖效果:
<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){
      let timer
      const x = customRef((track, trigger) => {
        return {
          get(){
            console.log(`有人从myRef这个容器中读取数据了,我把${value}`);
            track() //通知Vue追踪数据的变化(提前和get商量一下,让他认为这个value是有用的)
            return value
          },
          set(newValue){
            console.log(`有人把myRef这个容器中的数据改为了:${newValue}`);
            clearTimeout(timer)
            timer = setTimeout(() => {
              value = newValue
              trigger() //通知Vue去重新解析模板
            }, 500);
          }
        }
      })
      return x
    }
    // let keyWord = ref('hello') //使用Vue提供的ref
    let keyWord = myRef('hello') //使用程序员自定义的ref
    return {keyWord}
  }
}
</script>

5. provide 与 inject

  • 作用:实现祖与后代组件间通信

  • 套路:父组件有一个 provide 选项来提供数据,后代组件有一个 inject 选项来开始使用这些数据

  • 具体写法:

    1. 祖组件中:
setup(){
	......
    let car = reactive({name:'奔驰',price:'40万'})
    provide('car',car)
    ......
}
  1. 后代组件中:
setup(props,context){
	......
    const car = inject('car')
    return {car}
	......
}

6. 响应式数据的判断

  • isRef:检查一个值是否为一个ref对象
  • isReactive:检查一个对象是否是由reactive创建的响应式代理
  • isReadonly:检查一个对象是否由readonly创建的只读代理
  • isProxy:检查一个对象是否是由reactive 或者 readonly 方法创建的代理
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值