概念
按照文档中的说明:customRef
可以用来创建一个自定义的 ref
,并对其依赖项跟踪和更新触发进行显式控制。它需要一个工厂函数,该函数接收 track
和trigger
函数作为参数,并且应该返回一个带有 get
和 set
的对象。
其实大致意思就是,我们可以按照自己的业务需求去自定义封装一个ref
对象,在其内部可以使用get
和 set
去跟踪或更新数据,有点计算属性内味了哈~
应用场景
第一个应用场景就是官网文档中所提到的:可以用来实现防抖函数。
直接上代码:
<template>
<input
v-model="text"
>
</template>
<script setup lang="ts">
import { customRef } from 'vue'
function useDebouncedRef<T> (value: T, delay: number) {
let timer: any = null
return customRef<T>((track, trigger) => ({
get () {
track()
return value
},
set (newValue) {
clearTimeout(timer)
timer = setTimeout(() => {
value = newValue
// ...do something
trigger()
}, delay)
}
}))
}
const text = useDebouncedRef<string>('', 2000)
</script>
代码很简单,相信大家一看就能懂~
第二个应用场景就是可以用来做一个加强型的计算属性。
在Vue3中,computed创建出来的计算属性是只读的。什么意思呢?就是 computed 创建出来的属性,只能通过自身的 get 函数去跟踪其他属性来进行自身更新,算是一个比较坑的地方吧:
所以这个时候可以用 customRef 来实现一个加强版的 computed,代码如下:
<template>
<el-slider
v-model="value"
@change="handleSlider"
/>
</template>
<script setup lang="ts">
import { customRef } from 'vue'
function useDebouncedRef<T> (value: T) {
return customRef<T>((track, trigger) => ({
get () {
track()
return value
},
set (newValue) {
value = newValue
trigger()
}
}))
}
const value = useDebouncedRef<number>(0)
function handleSlider (e: number) {
value.value = e
}
</script>
<style lang="scss" scoped>
</style>
vue3的customRef实现自定义ref
customRef :
创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制,我们可以手动写set和get里的逻辑customRef
就像一辆手动挡车可玩性高,ref
就是自动挡车- 使用customRef实现防抖效果(在规定时间无论触发多少次方法,只执行最后一次),上代码
<template>
<!-- 实现一个效果,input输入数据,然后输入框下面同时显示数据但是,是延迟一秒之后 -->
<input type="text" v-model="word">
<span>{{ word }}</span>
</template>
<script>
import { customRef } from 'vue';
export default {
name: 'toRef',
setup() {
function myRef(value, delay) {
return customRef((track, trigger) => { // 这里有两个参数
let timer;// 用于接收定时器
return {
get() {
console.log('get调用了');
// 读取数据时会自动调用该方法
track();// 这个方法会通知vue追踪value的变化
return value;
},
set(newValue) {// 有个参数,是新修改的数据我们在set里进行赋值
console.log('set调用了');
clearTimeout(timer);// 使用前先清空定时器,免得创建很多定时器,在输入时就会出现抖动的效果
// 修改数据时会自动调用该方法
timer = setTimeout(() => {
value = newValue;
trigger(); // 这个方法会通知vue去解析模版(解析就会调用get去获取新的数据了)
}, delay);
}
}
})
};
let word = myRef('a', 1000);
return {
word
};
}
}
</script>
作用:创建一个自定义ref,比对其依赖项跟踪和更新触发进行显示控制
实现防抖效果:
// get:用于读数据进行调用 set:用于修改数据时进行调用
<template>
<div>
<input type="text" v-model="keyword" />
<h3>{{ keyword }}</h3>
</div>
</template>
<script>
import { ref, reactive, toRaw, customRef } from "vue";
export default {
setup() {
//自定义函数内部实现
function myref(value) {
let timer;
return customRef((track, trigger) => {
return {
get() {
// 读属性调用get
console.log("从myref中读取数据我把${value}");
track(); //通知vue追踪数据的变化
return value;
},
set(newvalue) {
//修改数据低啊用set
console.log(`修改了数据${newvalue}`);
value = newvalue; //进行修改数据
clearTimeout(timer); //进行防抖
timer = setTimeout(() => {
trigger(); //通知vue重新解析模板
}, 1000);
},
};
});
}
let keyword = myref("hellow"); //使用程序员自定义ref
return { keyword };
},
};
</script>
刚启动时:get调用两次进行读数据
当进行数据修改时:调用set函数,并且通过trigger()->track()进行数据的重新模板加载,实现响应式,
为了实现输入过快出现的抖动情况,