1、先看一效果:
2、实现思路:
- 使用定时器setTimeout和闭包实现常规防抖功能;
- 增加immediate字段控制第一次是否执行一次函数(true or false);
- 增加一个flag标识,在第一次执行时,将标识标识为true,同时通过使用定时器设置flag=false(防止用户是一次一次地触发,导致下一轮第一次无法触发事件);
- 在第二次触发回调函数时将flag设置false,为了第二轮触发防抖时,第一次也会执行函数。
3、防抖函数实现:
// 自定义防抖函数,支持传入等待时间(wait)、立即执行标识(immediate)等参数。
export const customDebounce = function (
fn: Function,
wait = 500,
immediate: boolean
) {
let timeID: number | null;
let flag = false;
return function (...args: any[]) {
// 控制每轮第一次进来时,都会执行一次函数,flag=true,并return
if (!timeID && !flag && immediate) {
fn.apply(this, args);
flag = true;
// 设置一个定时器,在wait毫秒后,将flag设置为false
// 防止用户每轮都是一次一次触发事件,导致flag一直为true,导致下一轮第一次无法再次触发事件
setTimeout(() => {
flag = false;
}, wait);
return;
}
if (timeID) {
clearTimeout(timeID);
}
timeID = setTimeout(() => {
fn.apply(this, args);
timeID = null;
// 控制每轮第二次执行操作时,设置flag为false
// 使得下一轮进来时,可以立刻执行一次函数
flag = false;
}, wait) as unknown as number;
};
};
4、vue3 + element-plus 组合式API单页面使用:
<script setup lang="ts">
import { ref } from "vue";
import { customDebounce } from "@/utils/utils";
const inputVal = ref();
const inputChange = customDebounce(
args => {
console.log("函数执行了", args);
},
1000,
true
);
</script>
<template>
<div class="custom-debounce">
<el-input v-model="inputVal" @input="inputChange" />
</div>
</template>
<style scoped lang="scss"></style>