防抖和节流

今日吃炒饭 2024-07-18 15:11:00 阅读 86

1. 防抖,回城-执行完成区间计时的一次

限时内,多次触发,只执行最后一次,并清空计时器。未计时完就一直清除计时器。

思路:利用闭包,保存回调函数的计时器。判断计时器是否存在,是-清除原计时器。计时器内调用事件处理函数。

注意:这里要搞清楚返回的匿名函数才是绑定的点击事件,而非 debounce 函数。匿名函数可以访问父函数debounce 声明的 timer,每次调用匿名函数时,timer 的数据得到保留。

<code><button>防抖-计时器</button>

<button>防抖-非计时器</button>

// 使用计时器

let btn = document.querySelector('button');

btn.addEventListener('click', debounce(handler));

// 事件处理函数

function handler(e) {

console.log(e);//!未传入参数时为undefine

console.log(this);//!未修改时为window

}

// 防抖函数

function debounce(fn) {

let timer;

// 新的事件会覆盖旧的事件,直到最后一件事等待1s后执行

return function (e) {// 返回作为回调事件

let _this = this;// 注意:es5中计时器的this只能指向window,用箭头函数可继承父业

if (timer) clearTimeout(timer);

timer = setTimeout(function () {

// 传入函数调用,提高可复用性

fn.call(_this, e); //!修改this,得去记,得去用啊宝宝:call/bind/apply

}, 1000)

}

}

也可以用节流的计时方式。

// 不使用计时器

let btn1 = document.querySelector('.liu');

btn1.addEventListener('click', (function () {

let currTime = Date.now();

return function (e) {

let nowTime = Date.now();

if (nowTime - currTime < 3000) { // 时效内点击,刷新计时器

currTime = nowTime;

return;

}

// 调用处理函数

console.log(e)

console.log(this)

currTime = nowTime; // 处理完毕,刷新计时器

}

})())

2. 节流,只执行第一次-区间内禁止触发第二次

思路:记录第一次执行调用的时间戳,超时才能执行下一次调用,并重置起始时间。

限时内,多次触发,只执行第一次,直到计时结束。(合理来说应该是直到第一个执行完毕,可以设置标记,执行完修改标记,作为锁)

?疑问:这里的标记,如果是c++存在指针,可以传引用,事件处理函数可以直接修改指针值,js 没有可以使用指针一说,要怎样实现指针的能力?

<code>// 节流:多次触发,只执行第一个,直到第一个执行完

window.addEventListener('scroll', throttle(handlerScroll, 1000));

// 事件处理函数

function handlerScroll(e) {

console.log(e);

console.log(this);

}

// 节流函数

function throttle(fn, delay) {

let prevTime = Date.now();

return function (...arg) {

let nowTime = Date.now();

if (nowTime - prevTime > delay) { // 区间计时结束,执行处理,并刷新起始时间

fn.apply(this, arg);

prevTime = Date.now();

}

}

}



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。