防抖
为什么需要防抖?
像鼠标缩放监听,输入框输入监听等高频发触发操作只需触发一次,需要等用户高频事件完了,再进行事件操作。
防抖实现:事件触发-》开启一个定时器-》如果再次触发,则清除上一次的,重新开一个定时器-》定时到,触发操作
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="http://ajax.aspnetcdn.com/ajax/jQuery/jquery-1.8.0.js"></script>
<title>防抖示例</title>
</head>
<body>
<input type="text" id="input" />
<script type="text/javascript">
var oInput = $("input");
oInput.keyup(
debounce(() => {
var val = oInput.val();
console.log("当前输入值: " + val);
}, 1000) //每一秒执行一次
);
//防抖
function debounce(fn, delay) {
let timer = null;
return function () {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
};
}
</script>
</body>
</html>
节流
为什么需要节流?
防抖存在的一个问题,事件会一直等到用户完成操作后一段时间再操作,如果一直操作,会一直不触发。正确思路:第一次操作触发事件,后面的操作等这次触发事件完成后再触发下一次。
某个操作希望上一次的完成后再进行下一次,或者说希望间隔一定时间触发一次。如前端向后端发送一次请求,希望后端响应请求后才能再次发送请求。
节流实现:事件触发-》操作执行-》关闭阀门-》阀门关闭,后续触发无效-》一定时间后,阀门打开-》操作可再次触发
示例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>节流示例</title>
</head>
<body>
<input type="text" id="input" />
<script type="text/javascript">
var oInput = document.getElementById("input");
oInput.oninput = throttle((e) => {
console.log("当前输入值", e.target.value);
}, 1000); //每一秒执行一次
//节流
function throttle(fn, delay) {
let valid = true; //初始阀门为打开状态
return function () {
if (valid) {
setTimeout(() => {
fn.apply(this, arguments);
valid = true; //执行完触发事件后打开阀门
}, delay);
valid = false; //开始执行触发事件时关闭阀门
} else {
return false;
}
};
}
</script>
</body>
</html>
防抖和节流相同点和不同点
相同点:都是为了阻止操作高频触发,从而浪费性能
不同点:防抖是多次触发只生效最后一次。适用于只需要一次触发生效的场景
节流是让操作每隔一段时间才能触发一次。适用于多次触发要多次生效的场景
在实现防抖和节流功能时,可以直接使用Lodash的debounce和throttle函数