防抖,单位时间内,频繁触发,只执行最后一次
效果演示
-
优化前,不断触发,浪费性能
-
优化后,只在指定时间内触发
演示代码
import debounce from "/node_modules/lodash-es/debounce.js";
const oBox = document.getElementById("box");
let index = 0;
function move() {
this.innerHTML = index++;
}
//默认进来调用一次
move.call(oBox);
//使用防抖
oBox.addEventListener("mousemove", debounce(move, 1000));
//不使用防抖
// oBox.addEventListener("mousemove", move);
//自己封装的防抖
function _debounce(fn, delay) {
clearTimeout(this.timeId);
this.timeId = setTimeout(() => {
move.call(this);
}, 1000);
}
#box{
width: 100px;
height: 100px;
background: red;
color:#fff;
text-align: center;
cursor: pointer;
}
<div id="box"></div>
封装优化
function _debounce(fn, delay) {
//默认进来调用一次
move.call(oBox);
return function () {
clearTimeout(fn.timeId);
fn.timeId = setTimeout(() => {
move.call(this);
}, delay);
};
}
节流,单位时间内,频繁触发,只执行第一次,期间触发不执行,500s再执行
窗口大小改变时的布局调整:当用户快速调整窗口大小时,节流可以确保在每个时间段内只执行一次布局调整操作,避免过度渲染。
滚动事件的处理:滚动事件可能会非常频繁地触发,节流可以限制滚动事件处理器的执行频率,提高性能。
使用场景: 比如: 监听滚动条,每隔一段时间计算一次位置
在定时器里面是无法清除定时器的,这是一个bug,在定时器外面可以清除
,所以必须手动重置为null
封装节流
oBox.addEventListener("mousemove", _throttle(move, 500));
function _throttle(fn, delay) {
//默认进来调用一次
fn.call(oBox);
const mowTime = Date.now();
return function () {
if (fn.timeId) return;
fn.timeId = setTimeout(() => {
fn.call(this);
// 在定时器里面是无法清除定时器的,这是一个bug,在外面可以清除
clearTimeout(fn.timeId);
// fn.timeId = null;
}, delay);
};
}
function _throttle2(fn, delay) {
let now = Date.now();
// 第一次进来,直接执行
fn.call(oBox);
// 第二次进来,判断是否超过了规定时间
// 超过了规定时间,执行
return function () {
const t = Date.now() - now - delay;
if (t >= 0) {
fn.call(this);
now = Date.now();
}
};
}
不手动重置定时器,触发是没反应的