天天看点

Vue3 Ref全家桶

Ref全家桶

1、Vue+TS定义ref数据类型

方法一:

import { ref } from 'vue';
type T = {
    name: string | number;
};
// 也可以让ts自己做类型推导
let message = ref<T>({
    name: '111',
});
           

方法二:对于类型比较复杂vue提供了一个interface

vue内部定义了这个接口
interface Ref<T> {
	value: T
}
           
import { ref } from 'vue';
import type {Ref} from 'vue'
type T = {
    name: string | number;
};
// Ref是vue提供的一个interface
let message: Ref<T> = ref({
    name: '111',
});
           

2、手写customRef

import { customRef } from 'vue';

function MyRef<T>(value: T) {
    return customRef((track, trigger) => {
        return {
            get() {
                //收集依赖
                track();
                return value;
            },
            set(newVal) {
                value = newVal;
                // 触发依赖
                trigger();
            },
        };
    });
}
// 使用
const obj = MyRef<string>('1111');
           

应用场景:防抖

import { customRef } from 'vue';
function MyRef<T>(value: T) {
    let timer: any;
    return customRef((track, trigger) => {
        return {
            get() {
                //收集依赖
                track();
                return value;
            },
            set(newVal) {
                clearTimeout(timer);
                timer = setTimeout(() => {
                    value = newVal;
                    timer = null;
                    // 触发依赖
                    trigger();
                }, 300);
            },
        };
    });
}
const obj = MyRef<string>('1111');
           

3、shallowRef作用:创建一个浅层次的ref,只会监听到

.value

变化。

注意:它里面的值不是响应式的。

let num1: Ref<T> = shallowRef({
    name: '111',
});
num1.value.name = '222'//这样修改页面不会变化,这个name属性是非响应式的
num1.value = {name:'2222'}//这样修改页面会变化,这样修改可以被监听
           

注意:ref和shallowRef不要混用,ref会使shallowRef也变成生层次的响应数据。

ref和reactive的区别:

  1. 定义数据角度:
    1. ref用于定义基本数据类型,
    2. reactive用于定义引用数据类型
    3. 注意:ref也能定义引用数据类型,其内部会自动通过reactive转为代理对象。
  2. 原理角度:
    1. ref通过Object.defineProperty()的get与set来实现数据响应式(数据劫持)。
    2. reactive通过使用Proxy来实现响应式,并通过Reflect操作源对象内部的数据。
  3. 使用角度:
    1. ref在操作数据时要.value,在模板中不用
    2. reactive在操作数据和模板中均不用

4、triggerRef函数的作用:接收一个ref对象作为参数,强制更新收集的依赖。

5、isRef函数的作用:接收一个对象作为参数,判断是不是一个Ref对象。

6、ref在模板中使用获取dom元素

<template>
    <div ref="dom">111</div>
    <button @click="change">修改</button>
</template>

<script setup >
import { ref } from 'vue';
// 定义的变量名要与模板中的一致
const dom = ref<HTMLDivElement>();
const change = () => {
    console.log(dom.value?.innerText);
};
</script>