vue3x——shallowReactive和shallowRef、readonly和shallowReadonly、toRaw与markRaw、customRef

86 篇文章 0 订阅
73 篇文章 0 订阅

Vue3.x

其他CompositionAPI
1.shallowReactive和shallowRef

​ shallowReactive:只处理对象最外层属性的响应式(浅层响应式)

​ shallowRef:只处理基本数据类型响应式,不进行对象的响应式处理

​ 什么时候使用?:

​ 如果有一个对象数据,结构比较深,但变化时只是最外层属性变化===>shallowReactive

​ 如果有一个对象数据,后续功能不会修改该对象中的属性,而是生新的对象来替代====>shallowRef

<template>
  <div>
    <p>{{ obj }}</p>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>工作:{{ job.job1.name }}</p>
    <p>薪资:{{ job.job1.salary }}K</p>
    <button @click="name += '-'">修改姓名</button>
    <button @click="age++">修改年龄</button>
    <button @click="job.job1.salary++">加薪</button>
    <hr />
    <p>num的值:{{ num.y }}</p>
    <button @click="num.y++">num+1</button>
  </div>
</template>

<script>
// shallowReactive:浅层次的响应式,只响应第一层的数据,不能深层的响应
// shallowRef:不去处理对象数据类型的数据,不会形成响应式数据。ref处理对象类型的数据,底层还是求助reactive变成了proxy对象,从而形成响应式
import { reactive, toRefs, shallowReactive,shallowRef, ref } from "vue";
export default {
  setup() {
    // let obj = reactive({
    let obj = shallowReactive({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    // let num = ref({y:0});//y值可修改,是响应式
    let num = shallowRef({y:0});//y值只能显示,不处理对象类型的数据
    return {
      obj,
      ...toRefs(obj),
      num,
    };
  },
};
</script>

<style>
</style>
2.readonly和shallowReadonly

​ readonly:让一个响应式数据变为只读的(深只读,全部属性都是只读)

​ shallowReadonly:让一个响应式数据变为只读(浅只读,第一层属性只读,其余层属性可读写)

​ 应用场景:不希望数据被修改时

<template>
  <div>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>工作:{{ job.job1.name }}</p>
    <p>薪资:{{ job.job1.salary }}K</p>
    <button @click="name += '-'">修改姓名</button>
    <button @click="age++">修改年龄</button>
    <button @click="job.job1.salary++">加薪</button>
    <hr />
    <p>num的值:{{ num }}</p>
    <button @click="num++">num+1</button>
  </div>
</template>

<script>
import { reactive, toRefs, ref,readonly,shallowReadonly } from "vue";
export default {
  setup() {
    let obj = reactive({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    let num=ref(0);
    // 接收一个响应式数据,加工后返回一个数据,里面的数据都不可以修改,
    // 原先的obj(可读写)被新的obj(只读)覆盖
    // 使用场景:数据是别人定义的,你拿过来用,但是不能写,只能读,所以在拿过来之后,就用readonly处理加工返回一个只能读的数据
    // obj = readonly(obj);
    // 接收一个响应式数据,返回一个新的数据,该数据的第一层属性只能读,不能写,除了第一层,其余层次的属性都可读写
    obj = shallowReadonly(obj);

    return {
      ...toRefs(obj),
      num,
    };
  },
};
</script>

<style>
</style>

使用ref和reactive定义数据,是为了将普通的数据(基本数据类型、引用数据类型)变成响应式的数据

3.toRaw与markRaw

toRaw:

​ 作用:将一个由reactive生成的响应式对象转为普通对象

​ 使用场景:用于读取响应式对象对应的普通对象,对这个普通的所有操作,不会引起页面的更新

markRaw:

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

​ 应用场景:

	1. 有些值不应该被设置为响应式的,例如复杂的第三方类库等
	2. 当渲染具有不可变数据源的大列表时,跳过响应式转换可以提高性能
<template>
  <div>
    <p>姓名:{{ name }}</p>
    <p>年龄:{{ age }}</p>
    <p>工作:{{ job.job1.name }}</p>
    <p>薪资:{{ job.job1.salary }}K</p>
    <button @click="name += '-'">修改姓名</button>
    <button @click="age++">修改年龄</button>
    <button @click="job.job1.salary++">加薪</button>
    <hr />
    <p>num的值:{{ num }}</p>
    <button @click="num++">num+1</button>
    <hr />
    <!-- <p>原始的obj:{{ obj }}</p> -->
    <button @click="showRawObj">显示原始的obj</button>
    <hr />
    <p v-show="obj.show">{{ obj.show }}</p>
    <button @click="add">添加一个属性</button>
    <button @click="obj.show.w++">w+</button>
    <button @click="obj.show.h++">h+</button>
  </div>
</template>

<script>
import { reactive, toRefs, ref, toRaw, markRaw } from "vue";
export default {
  setup() {
    let w = "";
    let h = "";
    // proxy对象
    let obj = reactive({
      name: "张三",
      age: 22,
      job: {
        job1: {
          name: "web工程师",
          salary: 20,
        },
      },
    });
    // RefImpl对象
    let num = ref(0);
    function showRawObj() {
      console.log(obj);
      // 将proxy类型的obj,还原成原始Object类型
      // toRaw只能转变reactive定义的数据
      const p = toRaw(obj);
      console.log(p);
    }
    function add() {
      let newObj = { w: 46, h: 158 };
      //在响应式对象身上添加任何属性,都是响应式的
    <p>体重:{{w }}kg</p>
      // obj.show = newObj;
      // 标记newObj,使其不再是响应式
      obj.show = markRaw(newObj);
      console.log(obj);
    }
    // setup执行一次,就return一次,setup在beforeCreate之前执行一次
    return {
      num,
      obj,
      ...toRefs(obj),
      showRawObj,
      add,
      w,
      h,
    };
  },
};
</script>

<style>
</style>

4.customRef

作用:创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显式控制

实现防抖效果:

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

<script>
import { customRef, ref } from "vue";
export default {
  name: "App",
  setup() {
    // 自定义ref
    // 形参value是调用这个自定义ref传入的参数(旧值)
    function myRef(value, delay) {
      console.log(value);
      // 是自定义的,所以要有自己写的逻辑,所以参数是一个回调函数
      const keys = customRef((track, trigger) => {
        let timer;
        return {
          // 读数据时调用
          get() {
            console.log("有人读取数据");
            // 4.通知vue追踪数据(实参,value)的改变,
            // 若是不用track追踪,get里面的value就一直是初始值
            track();
            // 3.解析模板,再次调用get,
            return value;
          },
          // v-model绑定的数据改变了,就调用set(修改数据)
          // 这个val是value改变后的值(新值)
          set(val) {
            // 调用set时,先清除掉上一个定时器
            clearTimeout(timer);
            console.log("有人修改数据了");
            // 1.先改数据——value
            // value = val;
            // 2.通知vue重新解析模板
            // trigger();
            // 延迟解析模板
            timer = setTimeout(() => {
              value = val;
              trigger();
            }, delay);
          },
        };
      });
      return keys;
    }
    // let keyWord = ref("hello");//使用vue提供的ref(自动)
    let keyWord = myRef("hello", 300); //手动

    return {
      keyWord,
    };
  },
};
</script>

<style>
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值