customRef
customRef()
是 Vue 3 中新增的 API,用于创建自定义 ref,并对其依赖项跟踪和更新触发进行显式控制。
用途
- 实现防抖/节流:通过控制依赖项收集和更新触发时机,可以实现防抖/节流功能。
- 自定义计算属性:可以根据特定逻辑计算值,并控制何时更新视图。
- 优化性能:可以避免不必要的更新,提升性能。
工作原理
customRef()
接收一个工厂函数作为参数,该函数接收 track
和 trigger
两个函数作为参数,并返回一个带有 get
和 set
方法的对象。
- track:用于收集依赖项。在
get
方法中调用,收集该 ref 所依赖的响应式数据。 - trigger:用于触发更新。在
set
方法中调用,通知依赖项更新视图。
示例:
const count = customRef((track, trigger) => {
let num = 0;
return {
get: () => num,
set: (val) => {
num = val;
trigger();
},
};
});
const update = () => {
count.value++;
};
解释:
track
和trigger
函数分别用于收集依赖项和触发更新。get
方法返回当前值。set
方法更新值并触发更新。
与 ref 的区别
ref
- 是 Vue 3 中用于创建响应式变量的 API。
- 更简单易用,适用于大多数场景。
customRef
- 提供对依赖项跟踪和更新触发更细粒度的控制。
- 更灵活,适用于需要更精细控制的场景。
应用场景
customRef允许我们通过获取或设置一个变量的值时进行一些额外的操作,而不需要侦听这个变量进行额外的操作。
实例 1
**目的:**我们可以通过触发counter
的getter
来获取本地存储的值,即直接counter.value
就能获取到了,而不是通过调用一个方法。同样地,我们也可以通过触发counter
的setter
来设置本地存储的值counter.value=1
<script setup>
import { customRef } from "vue";
function useLocalStorage(key: string, initialValue: any) {
const value = customRef((track, trigger)=>{
return {
get(){
track()
return localStorage.getItem(key) ?? initialValue
},
set(v){
localStorage.setItem(key, v)
trigger()
}
}
})
return value
}
const counter = useLocalStorage("counter", 0)
const update = () => {
counter.value++
}
</script>
<template>
<p>Counter: {{ counter }}</p>
<button @click="update">
Update
</button>
</template>
??是 ES11 中新增的运算符,表示当左边的操作数为 null 或 undefined 时,返回其右侧的操作数,否则返回左侧的操作数
实例 2
目的:实现一个防抖的 ref
<script setup>
import { watch, customRef } from "vue"
function useDebouncedRef(delay = 500) {
return customRef((track, trigger)=>{
let timer
let temp
return {
get(){
track()
return temp
},
set(v){
timer && clearInterval(timer)
timer = setInterval(()=>{
temp = v
trigger()
}, delay)
}
}
})
}
const text = useDebouncedRef()
watch(text, (value) => {
console.log(value)
})
</script>
<template>
<input v-model="text" />
</template>
本文由mdnice多平台发布
原文链接:https://juejin.cn/post/7353453349998559258 作者:小羊lbg