防抖函数
实现原理
在事件被触发 n 秒后再执行回调,如果在这 n 秒内又被触发,则重新计时。
适用场景
按钮提交场景**:防止多次提交按钮,只执行最后提交的一次
搜索框联想场景**:防止联想发送请求,只发送最后一次输入
<button onclick="func()">按钮</button>
/**
* @param {Function} func 需要防抖处理的函数
* @param {Number} wait 时间间隔
* @return {Function} 将 debounce 处理结果当作函数返回
*/
function debounce(func, wait) {
// 通过闭包缓存一个定时器 id
let timeout;
// 将 debounce 处理结果当作函数返回
// 触发事件回调时执行这个返回函数
return function () {
const context = this
const args = arguments
// 如果已经设定过定时器就清空上一次的定时器
if (timeout) clearTimeout(timeout)
// 开始设定一个新的定时器,定时器结束后执行回调函数 func
timeout = setTimeout(function () {
func.apply(context, args)
}, wait)
}
}
// 执行 debounce 函数返回新函数
const func = debounce(() => {
console.log("func 防抖函数执行了" + Date.now())
}, 1000)
// 停止滑动 1 秒后执行函数
document.addEventListener('scroll', func)
vue3 实现防抖
<template>
<el-button type="primary" @click="debounce($event)">primary</el-button>
<!-- <div @click="debounce($event)">122</div> -->
</template>
<script lang="ts" setup name="debounce">
import { ref } from "vue";
let timer = ref("") as any;
function debounce(_, immediated = false, timeout = 2000) {
return (function () {
console.log(timer.value);
console.log(immediated);
if (immediated) {
console.log("执行回调12");
return;
}
if (timer.value) clearTimeout(timer.value);
timer.value = setTimeout(() => {
console.log("执行回调");
}, timeout);
})();
}
</script>
<style></style>
节流函数
实现原理
规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
适用场景
- 拖拽场景:固定时间内只执行一次,防止超高频次触发位置变动
- 缩放场景:监控浏览器 resize
代码实现
// 节流
dothrotle(wait = 2000) {
if(!this.flag) return
if(this.flag){
console.log(1133);
this.flag = false
}
this.timer = setTimeout(() => {
this.flag = true
}, wait);
},
vue3实现
<template>
<el-button type="primary" @click="throtle($event)">throtle</el-button>
</template>
<script lang="ts" setup name="throtle">
import { ref, unref } from "vue";
let flag = ref(true);
function throtle(_, immediated = false, timeout = 2000) {
return (function () {
console.log(immediated);
if (immediated) {
console.log("执行回调12");
return;
}
console.log(unref(flag));
if (!flag.value) return;
flag.value = false;
setTimeout(() => {
flag.value = true;
console.log("执行回调");
}, timeout);
})();
}
</script>
<style></style>
项目上封装使用的防抖函数
/**
* 简易防抖函数
* @param {Function} func -防抖目标函数
* @param {Number}} gap - 防抖时间间隔
*/
export const debounce = ( func, gap ) => {
let timer
return function () {
timer && clearTimeout( timer )
timer = setTimeout( () => {
func.apply( this, arguments )
}, gap )
}
}