首先先画一个DIV 用于接下来的展示
<div
id="content"
style="
height: 150px;
line-height: 150px;
text-align: center;
color: #fff;
background-color: #ccc;
font-size: 80px;
"
></div>
let num = 1;
let content = document.getElementById("content");
function count() {
content.innerHTML = num++;
}
普通状态
先来看看鼠标在DIV上面移动并且不进行防抖或者节流的表现,
content.onmousemove = count;
随着鼠标的移动,数字是不断变大的,如果需要操作大量的DOM 或者请求接口,就不太合适了。
防抖 debounce
防抖,就是值触发事件后的N秒内函数只会执行一次,如果N秒内又触发了事件,则会重新触发计算函数执行时间,可以用于网页缩放,input输入等等
防抖可以分为两种情况,一种是鼠标移动立刻执行,还有一种是鼠标移动停下之后才会执行
function debounce(fn, time, immediate) {
let canRun = true;
let timeout;
if (immediate) {
return function () {
if (canRun) {
canRun = false;
fn.apply(this, arguments);
}
clearTimeout(timeout);
timeout = setTimeout(() => {
canRun = true;
}, time);
};
} else {
return function () {
if (timeout) {
clearTimeout(timeout);
}
timeout = setTimeout(() => {
fn.apply(this, arguments);
}, time);
};
}
}
fn为执行函数,time为防抖时间,immediate是否立刻执行
先看立即执行的版本,可以看出鼠标移上去的一瞬间数字加1,然后无论怎么移动都不会移动,除非两秒之后在移动
content.onmousemove = debounce(count, 2000, true);
然后是延后执行的版本,鼠标移动之后停止两秒之后数字加1,期间无论怎么移动都不会加1
content.onmousemove = debounce(count, 2000, false);
节流 throttle
节流,指的是连续触发事件,但是在N秒内只会执行一次 传参和防抖差不多,可以使用定时器或者时间戳,这边使用定时器演示
function throttle(fn, time, immediate) {
let canRun = true;
let timeout;
if (immediate) {
return function () {
if (canRun) {
canRun = false;
fn.apply(this.arguments);
setTimeout(() => {
canRun = true;
}, time);
}
};
} else {
return function () {
if (canRun) {
canRun = false;
setTimeout(() => {
fn.apply(this.arguments);
canRun = true;
}, time);
}
};
}
}
首先是立即执行版本,鼠标移动数字立即加1,然后每一秒加1
content.onmousemove = throttle(count, 1000, true)
然后是延迟执行版本,鼠标移动在一秒后数字立即加1,然后每一秒末尾加1
content.onmousemove = throttle(count, 1000, false);