在前端的开发过程中,涉及到与用户交互的过程中是基本上都是需要处理的,常规操作就是在对应位置加上防抖或者节流。
加上防抖或者节流的作用:一是为了防止用户频繁操作;二是为了节约一定的服务器资源,减少资源浪费的情况。
(1)防抖
指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。也就是说,短时间内不重复触发一个事件。
假如我们设置了一个等待时间 3 秒的函数,在这 3秒内如果遇到函数调用请求就重新计时 3 秒,直至新的 3 秒内没有函数调用请求,此时执行函数,不然就以此类推重新计时。
防抖函数(debounce.js):
/*
fn 需要处理的函数
dealy 时间间隔
*/
const debounce = (fn, delay=1000)=> {
// 通过闭包缓存一个定时器 timer
let timer = null;
// 将 debounce 处理结果当作函数返回
// 触发事件回调时执行这个返回函数
return function (...args) {
const that = this;
// 如果已经设定过定时器就清空上一次的定时器
if (timer) {
clearTimeout(timer);
}
// 开始设定一个新的定时器,定时器结束后执行传入的函数 fn
timer = setTimeout(function () {
fn.apply(that, args);
}, delay);
}
}
export default debounce;
页面使用:
<input type="text" @input="inputVal">
<script setup>
const inputVal = debounce((e) => {
console.log('防抖处理函数', e.target.value);
}, 1000);
</script>
(2)节流
点击事件,在一段事件内连续点击,指定时间内只触发一次
节流函数(throttle.js)
/*
fn 需要处理的函数
dealy 时间间隔
*/
const throttle = (fn, delay = 1000) => {
// 通过闭包缓存一个定时器 timer
let timer = null;
// 将 throttle 处理结果当作函数返回
// 触发事件回调时执行这个返回函数
return function (...args) {
if (timer) {
return;
}
const that = this;
// 开始设定一个新的定时器,定时器结束后执行传入的函数 fn
timer = setTimeout(() => {
timer = null;
}, delay);
fn.apply(that, args);//执行函数
}
}
export default throttle;
页面使用
<input type="text" @input="inputVal">
<script setup>
import throttle from '../utils/throttle';
const inputVal = throttle((e) => {
console.log('节流处理函数', e.target.value);
}, 1000);
</script>
(3)在vue3中,新的防抖和节流函数实现方式:
customRef 函数
使用 customRef 函数创建一个自定义的 ref ,并对其依赖项跟踪和更新触发进行显示控制
customRef 接收一个函数作为参数,这个函数接收两个函数作为参数 track (通知vue需要追踪后续内容的变化) 和 trigger (通知vue重新解析模板)。
防抖函数(debounce.js):
import { customRef, ref } from 'vue';
const debounceRef = (data, delay = 500) => {
// 创建定时器
let timer = null;
// customRef 中会返回两个函数参数。一个是:track 在获取数据时收集依赖的;一个是:trigger 在修改数据时进行通知派发更新的。
return customRef((track, trigger) => {
return {
get() {
// 收集依赖
track();
// 返回当前数据
return data;
},
set(val) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
// 修改数据
data = val;
// 派发更新
trigger();
}, delay);
}
}
});
}
const val = debounceRef('', 1000);
页面实现
<input type="text" v-model='val'>
节流函数(throttle.js):
const throttleRef = (data, delay = 500) => {
// 创建定时器
let timer = null;
// customRef 中会返回两个函数参数。一个是:track 在获取数据时收集依赖的;一个是:trigger 在修改数据时进行通知派发更新的。
return customRef((track, trigger) => {
return {
get() {
// 收集依赖
track();
// 返回当前数据
return data;
},
set(val) {
if (timer) {
return;
}
timer = setTimeout(() => {
timer = null;
}, delay);
// 修改数据
data = val;
// 派发更新
trigger();
}
}
});
};
const inputVal = throttleRef('', 1000);
页面实现
<input type="text" v-model='inputVal'>