在阅读Vue3文档响应式基础时,看到了这个 API。觉得可能在某些场景下确实还是比较好用的,所以拿来记录一下。
概念
按照文档中的说明: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>
第二种场景仅代表个人想法,如有更好的建议,请大佬们指点一二