Vue3实用但冷门的API

今天给大家分享几个很少人用,但是又非常有用的 Vue3 的 API,废话不多说,我们开始!

readonly

顾名思义,是只读的意思,如果你的数据被这个 API 包裹住的话,那么修改之后并不会触发响应式,并且会提示警告。

<template>
    <div>{{ obj.age }}</div>
</template>

<script lang="ts" setup>
    import { readonly, reactive } from 'vue';
    let obj = reactive({
        name: 'sunshine lin',
        age: 20,
    });
    obj = readonly(obj);
    obj.age = 18;
</script>

<style></style>

应用场景:readonly 的用途一般用于一些 hooks 暴露出来的变量,不想外界去修改,比如我封装一个 hooks,这样去做的话,那么外界只能用变量,但是不能修改变量,这样大大保护了 hooks 内部的逻辑

shallowRef 

shallowRef 用来包住一个基础类型或者引用类型,如果是基础类型那么跟 ref 基本没区别,如果是引用类型的话,那么直接改深层属性是不能触发响应式的,除非直接修改引用地址,如下:

注意:改深层属性能改数据,只是没触发响应式,所以当下一次响应式触发的时候,你修改的深层数据会渲染到页面上。

应用场景:shallowRef 的用处主要用于一些比较大的但又变化不大的数据,比如我有一个表格数据,通过接口直接获取,并且主要用在前端展示,需要修改一些深层的属性,但是这些属性并不需要立即表现在页面上,比如以下例子,我只需要展示 name、age 字段,至于 isOld 字段并不需要展示,我想要计算 isOld 但是又不想触发响应式更新,所以可以用 shallowRef 包起来,进而减少响应式更新,优化性能。

    import { onMounted, shallowRef } from 'vue';
    interface IRow {
        name: string;
        age: 20;
        isold?: boolean;
    }
    //hooks
    export const useFetchData = () => {
        const list = shallowRef<IRow[]>([]);

        const fetchData = async () =>
            //模拟请求
            list.value = await new Promise<IRow[]>(resolve => {
                resolve(
                    new Array(1000).map(() => ({
                        name: 'sunshine_lin',
                        age: 20,
                    })),
                );
            })

    const checkIsold = ()=>{
        list.value.forEach(({age },index)=>{
            list.value[index].isold = age > 60;
        });
    };
    
    onMounted(()=>{
        fetchData();
    });

    return{
        list,
        checkIsold,
    }
};

    //页面中

    //只需要展示name age
    //不需要展示old
    const columns = ['name','age'];

    const {checkIsold,list } =useFetchData();
    //判断成员是不是老人
    checkIsold();

toRef & toRefs 

1.toRef

在使用 reactive 的时候会有一个苦恼,那就是解构出来了 name 并放到模板里渲染,但是当我们想改原数据的时候,发现 name 并不会更新,一旦结构失去响应式。

<template>
  <div class="about">
    <div>{{ obj.name }}</div>
    <div>{{ name }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, onBeforeMount, onMounted, reactive } from 'vue';

export default defineComponent({
  name: 'about',
  props: {},
  components: {},
  setup() {
    const obj = reactive({
      name:'wangHang',
      age:'20'
    });
    let {name} = obj;//将obj对象的name属性的值解构出来,并赋给了一个名为name的变量
    obj.name = 'wh123';

    onBeforeMount(() => {})
    onMounted(() => { })
    return {
      obj,
      name
    }
  }
})
</script>


渲染结果:

这时我们可以使用 toRef,这个时候我们直接修改 name 也会触发原数据的修改,修改原数据也会触发 name 的修改。

<template>
  <div class="about">
    <div>{{ obj.name }}</div>
    <div>{{ name }}</div>
  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRef } from 'vue';

export default defineComponent({
  name: 'Home',
  props: {},
  components: {},
  setup() {
    const obj = reactive({
      name:'wangHang',
      age:'20'
    });
    const name = toRef(obj,'name');

    //修改任何一个都会相互触发数据修改 (以下两个可单独)
    obj.name = 'wh123';
    name.value = 'wh456';

    return {
      obj,
      name
    }
  }
})
</script>

渲染结果:

2.toRefs

 但是如果是属性太多了,我们想一个一个去用 toRef 的话会写很多代码,所以我们可以使用 toRefs 一次性解构。

<template>
  <div class="about">
    <div>{{ name }}</div>
    <div>{{ age }}</div>
    <div>{{ hobbies }}</div>

  </div>
</template>

<script lang="ts">
import { defineComponent, reactive, toRef, toRefs } from 'vue';

export default defineComponent({
  name: 'toRefs',
  setup() {
    const obj = reactive({
      name:'wangHang',
      age:'20',
      hobbies:['a']
    });

    const {name,age,hobbies} = toRefs(obj);

    name.value = 'wh111';
    age.value = '12';
    hobbies.value = ['b'];
    // let {hobbies} = obj;

    return {
      obj,
      name,
      age,
      hobbies
    }
  }
})
</script>

toRaw & markRaw & unref

1.toRaw

toRaw 可以把一个响应式 reactive 转成普通对象,也就是把响应式对象转成非响应式对象

<template>
    <div class="toRow">
     <div>{{ rowObj.name }}</div>
    </div>
  </template>
  
  <script lang="ts">
  import { defineComponent, onMounted, reactive, toRaw} from 'vue';
  
  export default defineComponent({
    name: 'toRow',
    setup() {
      const obj = reactive({
        name:'wangHang',
        age:'20'
      });

      let rowObj = toRaw(obj);
      onMounted(()=>{
          rowObj.name = 'wh';//不会触发视图更新
      })
      
      return {
        obj,
        rowObj
      }
    }
  })
  </script>

 

2.markRaw

markRaw是一个用于标记对象的函数,它可以将一个对象标记为“非响应式”的,从而使其不会被Vue的响应式系统追踪和更新。具体来说,markRaw函数接受一个对象作为参数,并返回一个与该对象相同的对象,但是该对象被标记为“非响应式”。

<template>
    <div class="markRaw">
        请看控制台输出内容
    </div>
</template>
  
<script lang="ts">
import { defineComponent, markRaw, reactive } from 'vue';

export default defineComponent({
    name: 'markRaw',
    setup() {

        const obj = reactive({
            name: 'Tom',
            age: 18
        });

        const rawObj = markRaw(obj);

        console.log(rawObj.name); // 输出 'Tom'

        rawObj.name = 'Jerry';

        console.log(rawObj.name); // 输出 'Jerry'

        console.log(obj.name); // 输出 'Tom'

        return {
            obj,
        }
    }
})
</script>

通过访问rawObj.name,我们可以获取到obj对象的name属性的值。然而,当我们修改rawObj.name的值时,obj.name的值并没有发生变化,因为rawObj被标记为“非响应式”,不会被Vue的响应式系统追踪和更新。

3.unref

unref 相当于返回 ref 的 value

<template>
    <div class="unRef">
        请看控制台输出内容
    </div>
</template>
  
  <script lang="ts">
  import { defineComponent, ref, unref} from 'vue';
  
  export default defineComponent({
    name: 'unRef',
    setup() {
      const name = ref("wangHang");
      console.log(name);
      console.log(unref(name));//<==>console.log(name.value);
      
      return {
        name
      }
    }
  })
  </script>

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

聪明的墨菲特 (o.O)?

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值