Vue3新特性的学习(七)——toRef函数、customRef

396 阅读2分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情

今天主要是学习toRef的特点与作用,customRef在实战中的应用。

toRef函数的特点与作用

toRef为响应式对象上的某个属性创建一个ref引用,更新时引用对象会同步更新;

示例:

<template>
  <div>
    <div>{{ state.total }}</div>
    <button @click="update">更新数据</button>
  </div>
</template>
<script lang="ts">
import { defineComponent, reactive } from "vue";
export default defineComponent({
  name: "Home",
  setup() {
    let state = reactive({
      total: 10,
    });
    let update = () => {
      let total = state.total;
      total++;
    };
    return {
      state,
      update,
    };
  },
});
</script>

这么直接赋值给变量total,对total进行值得更新,视图是不会更新的;

引入toRef,使用toRef进行引用,改变total的值,视图就会更新了:

    let update = () => {
      //   let total = state.total;
      let total = toRef(state, "total");
      total.value++;
    };

还有一种情况也是不会更新视图的:

    let update = () => {
      //   let total = state.total;
    //   let total = toRef(state, "total");
      let total = toRef({ total: 10 }, "total");
      total.value++;
    };

注意:如果通过toRef创建的数据修改时,并不会触发视图界面的更新,因为toRef的本质是引用,与原始数据有关联。

customRef在实战中的应用

customRef用于自定义一个ref,可以显式地控制依赖追踪和触发反应,接受一个工厂函数,两个参数分别是用于追踪的track与用于触发响应的trigger,并返回一个带有getset属性的对象,在实际开发中可以实现防抖函数。

示例:给一个input框做个防抖处理:

使用customRef封装一个防抖函数:

import { customRef } from "vue";
export function useDebounced<T>(value: T, delay = 300, callback: Function) {
  let timer: any = null;
  return customRef((track, trigger) => {
    return {
      get() {
        track(); // 告诉vue追踪数据
        return value; // 这里返回的就是input传入的值
      },
      set(newVal: T) {
        // 使用clearTimeout和setTimeout实现防抖
        clearTimeout(timer);
        timer = setTimeout(() => {
          value = newVal;
          callback(value);
          trigger(); // 告诉vue去更新页面
        }, delay);
      },
    };
  });
}

然后在页面中引用,对input框的输入做一个防抖处理:

<template>
  <div>
    <div>
      <input type="text" v-model="keywords" />
    </div>
  </div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import { useDebounced } from "@/hook/debounced";
export default defineComponent({
  name: "Home",
  setup() {
    let keywords = useDebounced<string>("", 500, (val: string) => {
      console.log("输入的值", val);
    });
    return {
      keywords,
    };
  },
});
</script>

接下来继续学习Vue3的知识点~