函数的防抖
- 场景1: 点击按钮向服务器发送请求(需要一定的时间),当前请求之前再点击无效点击
- 方式1:通过一个变量,控制按钮是否可以点击
let loading = false;
SubmitEvent.onclick = async () => {
if(loading) return;
loading = true;
//这里是个伪代码
await this.$api.postSome({
id: 11,
remark: 777
})
loading = false;
}
- 方式2: 封装一个防抖函数(可以直接用)
const utils = (function () {
/**
* 清除定时器
* @param {*} timer
*/
const clearTimer = (timer) => {
if (timer) {
clearTimeout(timer);
}
return null;
}
/**
* 函数的防抖
* @param {Function} func 必填
* @param {Number} wait 触发频率规则
* @param {Boolean} imediate 控制是否是在开始触发
*/
const debounce = (func, wait, imediate) => {
if (typeof func !== "function") throw new Error('This is not a function');
if (typeof wait === "boolean") {
imediate = wait;
wait = undefined;
}
// 处理是不是有效数字
wait = +wait;
if (isNaN(wait)) wait = 300;
if (typeof imediate !== "boolean") imediate = false;
// hander处理
let timer = null;
// 用箭头函数处理掉this指向额问题如果不用就func.call(this);
return (...params) => {
// now 记录是否是立即执行[第一次执行,并且imediate为true]
let now = !timer && imediate;
// 清除定时器(清除之前的)
timer = clearTimer(timer);
timer = setTimeout(() => {
// 结束边界触发
if (!imediate) func(...params);
// 清除最后一个定时器
timer = clearTimer(timer);
}, wait);
// now为true,做该干的事情
if (now) {
func(...params);
}
}
}
return {
debounce
}
})();
函数的节流
- 一般的应用场景: input文本框的 keydown;keyup;input事件
const utils = (function () {
/**
* 清除定时器
* @param {*} timer
*/
const clearTimer = (timer) => {
if (timer) {
clearTimeout(timer);
}
return null;
};
/**
* 节流函数
* @param {Function} func
* @param {Number} wait
*/
const throttle = (func, wait = 300) => {
if (typeof func !== "function") throw new Error('This is not a function');
// 处理是不是有效数字
wait = +wait;
if (isNaN(wait)) wait = 300;
// handler
let timer = null,
previous = 0;//记录上一次触发的时间
return (...params) => {
let now = +new Date(),
remaining = wait - (now - previous);
if (remaining <= 0) {
// 说明2次触发的间隔时间超过设定的频率,则立即执行
func(...params);
previous = +new Date();
timer = clearTimer(timer);
} else if (!timer) {
// 间隔时间不足设定频率,而且还没设置定时器
timer = setTimeout(() => {
func(...params);
previous = +new Date();
timer = clearTimer(timer);
}, remaining);
}
}
};
return {
throttle
}
})();
<!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>Document</title>
<style>
* {
margin: 0;
padding: 0;
}
html,
body {
height: 5000px;
background-color: aquamarine;
}
</style>
</head>
<body>
<button id="btn">立即提交</button>
<script src="./utils.js"></script>
<script>
const btn = document.getElementById('btn');
const func = () => {
console.log(111111)
}
btn.onclick = utils.debounce(func, true)
// window.onscroll有一个默认的触发频率,是按照浏览器的最快反应时间
window.onscroll = utils.throttle(func, 1000);
</script>
</body>
</html>
总结
- 什么时候使用节流和防抖
- 防抖就是不管尼搞多少次,爷就给你一次
- 本身触发频率非常块但是我不需要这么快的频率