写在最前:最近公司项目有用到按钮的节流,于是想都没想直接下载lodash依赖导入,结果差强人意节流函数没有生效!!!不知道有没有小伙伴跟我一样......
import { debounce,throttle } from 'lodash';
throttle(fn,2000) //节流没有生效
所以干脆手写一个TS版的
- 防抖
function debounce<T extends (...args: any[]) => void>(fn: T, delay: number) {
let timer: ReturnType<typeof setTimeout> | null; // 定时器变量
return function (this: unknown, ...args: Parameters<T>) {
const context = this;
// 如果定时器存在,则清空定时器
if (timer) {
clearTimeout(timer);
}
// 在 delay 时间之后执行 fn 函数
timer = setTimeout(function () {
fn.apply(context, args);
}, delay);
};
}
- 节流
function throttle<T extends (...args: any[]) => void>(fn: T, delay: number) {
let timer: ReturnType<typeof setTimeout> | null; // 定时器变量
return function (this: unknown, ...args: Parameters<T>) {
const context = this;
// 如果 timer 存在,说明函数还未该执行
if (timer) return;
// 否则,创建定时器
timer = setTimeout(function () {
// 当函数执行时,将 timer 设为 null。
timer = null;
fn.apply(context, args);
}, delay);
};
}
写在最后:中途接手项目发现所有导入导出按钮都没有做节流,屎山的按钮一个个加点击事件真得通宵吧??想起来自定义指令刚好适用该场景,于是:
//节流自定义指令
import type { App, Directive } from 'vue';
export default function setupBtnThrottleDirective(app: App) {
app.directive("throttle", {
mounted(el, binding) {
console.log(binding)
const { delay = 1000, fn } = binding.value; // 默认1000
const throttledClick = throttle(fn,delay);
el.addEventListener('click', throttledClick);
el._throttledClick = throttledClick;
},
beforeUnmount(el) {
if (el._throttledClick) {
el.removeEventListener('click', el._throttledClick);
}
}
});
}
//main.ts注册指令
import setupBtnThrottleDirective from './directives';
const app = createApp(App);
setupBtnThrottleDirective(app)
//组件使用节流指令
<n-button v-throttle="{delay: 1500, fn: exportListedse}" type="primary">批量导出</n-button>
const exportListedse = ()=>{
console.log('导出)
}