什么是节流
如果持续触发事件,每隔一段时间只会会执行一次。
应用场景
DOM 元素拖拽
监听 scroll 滚动事件
计算鼠标移动的距离
一些知识点
const nowTime = new Date().valueOf(); // 获取当前时间戳
使用时间戳实现
const jieliu(fn, wait) {
let old = 0;
return function() {
const _this = this;
const args = arguments;
let now = new Date().valueOf();
if (now - old > wait) {
fn.apply(_this, args);
old = now;
}
}
}
使用定时器实现
function throttle(fn, wait) {
let flag = true;
return function() {
if (!flag) return;
const args = arguments;
flag = false;
setTimeout(() => {
fn.apply(this, args);
flag = true;
}, wait);
}
}
function throttle(fn, wait) {
let timer;
return function () {
if (timer) return;
const args = arguments;
timer = setTimeout(() => {
timer = null;
fn.apply(this, args);
}, wait);
};
}
使用时间戳和定时器结合实现
function throttle(fn, await, option = {}) {
let old = 0;
let timer;
return function () {
const _this = this;
const args = arguments;
let now = new Date().valueOf();
// 第一次触发立即执行
if (now - old > await && option.leading === true) {
if (timer) {
clearTimeout(timer);
timer = null;
} else {
fn.apply(_this, args);
old = now;
}
}
// 最后一次会触发
if (!timer && option.trailing === true) {
timer = setTimeout(() => {
timer = null;
old = new Date().valueOf();
fn.apply(_this, args);
}, await);
}
};
}
验证
<div id="box" style="background-color: #ccc; width: 500px; height: 500px;"></div>
const boxEle = document.getElementById('box');
function handler() {
console.log('123');
}
boxEle.addEventListener(
"mousemove",
throttle(handler, 3000, { leading: false, trailing: true })
);
总结
使用时间戳实现节流,第一次立即触发,最后一次不触发;
使用定时器实现节流,第一次不会立即触发,会在规定时间后触发,因为第一次执行就会开启定时器,最后一次会触发;
使用时间戳和定时器结合实现,第一次会立即触发,最后一次离开也会触发。