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