防抖和节流
防抖和节流
防抖
- 不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准
/**
* 防抖:不管事件触发频率多高,一定在事件触发 n 秒后才执行,如果在一个事件执行的 n秒内又触发了这个事件,就以新的事件的时间为准
* @callback fn -被调用的函数
* @param {number} [wait = 300] -定时器时间
* @param {boolean} [immediate = false] -是否要立即执行一次
*/
export function debounce(fn, wait = 300, immediate = false) {
// 参数验证
if (typeof fn != 'function')
throw Error("第一个参数必须是函数!");
if (typeof wait != 'number')
throw Error("第二个参数必须是数字!");
if (typeof immediate != 'boolean')
throw Error("第三个参数必须是布尔值!");
let timer = null;
// 返回一个函数
return function() {
// 是否要立即执行一次
if (!timer && immediate)
fn.apply(this, arguments);
// 每次触发事件时都取消之前的定时器
clearTimeout(timer);
// setTimeout 中使用箭头函数,就是让 this指向 返回的该闭包函数,而不是 debounce函数 的调用者
timer = setTimeout(() => {
fn.apply(this, arguments)
}, wait)
}
}
函数不能使用箭头函数,否则 this 执行会有问题
js使用
window.addEventListener('resize', debounce(function() {}, 200));
vue使用
mehtod: debounce(function() {}, 200)
节流
- 不管事件触发频率有多高,只在单位时间内执行一次。
使用时间戳
第一次事件肯定触发,最后一次不会触发(比如说监听 onmousemove,则鼠标停止移动时,立即停止触发事件)
function throttle(fn, wait) {
// 记录上一次执行的时间戳
let previous = 0;
return function(...args) {
// 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔,就执行函数,否则不执行
if(Date.now() - previous > wait) {
// 更新上一次的时间戳为当前时间戳
previous = Date.now();
fn.apply(this, args);
}
}
}
使用定时器
第一次事件不会触发(fn是放在 setTimeout中执行的,所以第一次触发事件至少等待 wait 毫秒之后才执行),最后一次一定触发
function throttle(fn, wait) {
// 设置一个定时器
let timer = null;
return function(...args) {
// 判断如果定时器不存在就执行,存在则不执行
if(!timer) {
// 设置下一个定时器
timer = setTimeout(() => {
// 然后执行函数,清空定时器
timer = null;
fn.apply(this, args)
}, wait)
}
}
}
定时器和时间戳结合
两者结合可以实现,第一次事件会触发,最后一次事件也会触发
/**
* 节流: 不管事件触发频率有多高,只在单位时间内执行一次
* 第一次事件和最后一次事件都触发
* @callback fn -被调用的函数
* @param {number} [wait = 300] -定时器时间
*/
export function throttle(fn, wait = 300) {
// 参数验证
if (typeof fn != 'function')
throw Error("第一个参数必须是函数!");
if (typeof wait != 'number')
throw Error("第二个参数必须是数字!");
// 设置一个定时器
let timer = null;
// 记录上一次执行的时间戳
let previous = 0;
return function() {
// 当前的时间戳,然后减去之前的时间戳,大于设置的时间间隔
if (Date.now() - previous > wait) {
clearTimeout(timer)
timer = null;
// 更新上一次的时间戳为当前时间戳
previous = Date.now();
fn.apply(this, arguments);
} else if (!timer) {
// 设置下一个定时器
timer = setTimeout(() => {
timer = null;
fn.apply(this, arguments);
}, wait)
}
}
}
使用方法和防抖一样
本文来自博客园,作者:懒惰ing,转载请注明原文链接:https://www.cnblogs.com/landuo629/p/14305945.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?