今天来简单介绍一个新的方法,使用自定义 ref 实现函数防抖。
1. 自定义 ref 的来源
自定义 ref 防抖函数来自于前端开发中的两个概念:Vue 的响应式系统 和 数防抖(Debounce)。
1、Vue 响应式系统:Vue 提供了 ref 和 watch 来实现响应式数据更新,开发者可以通过 ref 定义响应式数据,并通过 watch 监控变化。
2、防抖(Debounce):防抖是一个在高频事件中避免性能消耗的常见技术。它的核心思想是将多次频繁触发的操作合并为一次,确保在设定时间内,事件只触发一次。
将两者结合,可以利用 Vue 的 ref 和防抖逻辑,在前端表单输入、搜索框等场景中高效地管理用户输入、限制高频操作,提升应用性能。
2. 原始写法(无自定义 ref)
在没有自定义 ref 的情况下,通常直接在事件处理函数中实现防抖。
在 Vue 中,这种方法通常通过 watch 或者在模板中绑定事件。不使用 v-model 处理,因为它是实时改变的。
🌰
<template>
<input class="input" @input="handleInputChange($event.target.value)" />
<div class="content">{{ inputValue }}</div>
</template>
<script setup>
import { ref } from 'vue'
const inputValue = ref('')
// 原始防抖函数实现
const debounce = (fn, delay) => {
let timeout = null
return function (...args) {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
fn.apply(this, args)
}, delay)
}
}
// 使用防抖处理输入
const handleInputChange = debounce((value) => {
// 执行实际的输入处理逻辑
inputValue.value = value
console.log('输入内容:', value)
}, 300)
</script>
300ms 后,展示到 div 和 控制台中。
3. 自定义 ref 实现防抖(优化写法)
虽然原始写法可以满足基本的防抖需求,但在 Vue 中,我们希望利用其响应式特性,使数据的防抖处理与 Vue 的响应式系统深度结合。因此,使用自定义 ref 和 watch 可以更优雅地实现防抖逻辑。
🌰:
<template>
<div>
<input class="input" v-model="inputValue" />
<p>实时输入的值: {{ inputValue }}</p>
<p>防抖后的值: {{ debouncedValue }}</p>
</div>
</template>
<script setup>
import { ref, watch } from 'vue'
// 自定义防抖 ref 的 Hook
function useDebouncedRef(initialValue, delay = 300) {
const inputValue = ref(initialValue)
const debouncedValue = ref(initialValue)
let timeout = null
watch(inputValue, (newValue) => {
if (timeout) {
clearTimeout(timeout)
}
timeout = setTimeout(() => {
debouncedValue.value = newValue
}, delay)
})
return {
inputValue,
debouncedValue
}
}
// 使用自定义防抖 ref 实现
const { inputValue, debouncedValue } = useDebouncedRef('', 300)
</script>
展示为:
4. 利用 Vue 提供的 customRef 实现
不但可以自定义实现,还可以使用 Vue 提供专门产生一个自定义 ref 的API:customRef。
customRef 官方文档:https://cn.vuejs.org/api/reactivity-advanced
🌰:
<template>
<div>
<input class="input" v-model="debouncedInput" placeholder="输入防抖" />
<div class="content">{{ debouncedInput }}</div>
</div>
</template>
<script setup>
import { customRef } from 'vue'
// 创建防抖函数,返回一个 ref 数据
const useDebouncedRef = (initialValue, delay = 300) => {
let timer = null
return customRef((track, trigger) => ({
get() {
// 依赖收集
track()
return initialValue
},
set(val) {
clearTimeout(timer)
timer = setTimeout(() => {
// 派发更新
trigger()
initialValue = val
}, delay)
}
}))
}
const debouncedInput = useDebouncedRef('', 500) // 设置防抖延迟为500ms
</script>
当用户在输入框中输入内容时,debouncedInput 的值会被更新,但由于防抖的机制,输入内容的变化不会立即反映到视图中,而是会有一个延迟。
5. 优缺点
优点:
1、限制事件的触发次数,可以极大地降低性能损耗。
2、减少频繁发起请求,节省服务器资源,避免服务器过载。
3、在用户输入过程中,避免频繁触发事件可以使界面更加流畅,减少卡顿感,提升用户体验。
缺点:
在开发过程中引入额外的防抖逻辑和自定义处理,可能增加代码的复杂性,特别是在处理多个防抖场景时。