防抖
为什么要做防抖
有的操作是高频触发的,但有的操作频繁触发没有意义,只触发一次就好。
如短时间内多次缩放页面,我们不应该在整个缩放过程中都频繁的去触发监听,应在缩放定下来之后进行一次操作就好。
如监听输入框输入,不应该每按下一次按钮都去做监听事件的触发,应该是用户完成一段输入后,再进行触发。
操作一下就触发一下,浪费性能,很多高频事件只需要最后一个结果
也即,等用户高频事件完了,再进行事件操作
防抖怎么做
事件触发 --> 开启一个定时器 --> 如果再次触发,则清除上一次的,重写开一个 --> 定时到,触发操作
<!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>second</title>
</head>
<body>
<input type="text" id="inputid" />
<script>
// 操作不直接触发,搞个定时器,下次触发时再重新定时
// 封装成一个防抖工厂,传入一个函数告诉它要给哪个操作进行防抖,以及防抖的延时是多久,这样就能复用它
function debounce(fn, delay) {
let timer = null;
// return出一个新的加了防抖操作的函数
// 如果一直调用,防抖会将先前的时间都清掉,直到停下来后过delay时长后再触发
return function() {
// setTimeout(), setInterval()会返回一个ID,可将ID传给clearTimeout(), clearInterval()以取消执行
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, arguments);
}, delay);
}
}
let inputdom = document.getElementById("inputid");
// 原函数
// inputdom.oninput = function(event) {
// console.log(event.target.value);
// }
// 改造input监听实现,将输入监听变成防抖的,联想输入会更科学
inputdom.oninput = debounce(function(event) {
console.log(event.target.value);
}, 500);
</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>throttle</title>
</head>
<body>
<input id="inputid" />
<button id="sendAxios">请求</button>
<script>
let inputdom = document.getElementById("inputid");
// 写个节流工厂函数,方便后续调用
function throttle(fn, delay) {
// 定义阀门
let valid = true;
return function() {
if (valid) {
setTimeout(() => {
fn.apply(this, arguments);
valid = true;
}, delay);
valid = false;
} else {
// 若阀门本来就是关的,那就不进行操作,return个false
return false;
}
}
}
inputdom.oninput = throttle(function(event) {
console.log(event.target.value);
}, 200);
</script>
</body>
</html>
防抖和节流的对比
相同点
- 都是为了阻止操作高频触发,从而浪费性能。
区别
- 防抖:让你多次触发,只生效最后一次。适用于我们只需要一次触发生效的场景。
- 节流:让你的操作,每隔一段事件才能触发一次。适用于我们多次触发要多次生效的场景。