天天看點

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>