@[toc]
自定义JS工具类 相关类似的源码请看 https://gitee.com/ykang2020/my_utils (opens new window)
# 1. 浏览器事件触发
一些浏览器事件: window.onresize
、window.mousemove
等,触发的频率非常高,会造成界面卡顿
还有比如:用户疯狂点击,多次触发click事件;用户连续输入,多次触发keyup事件等
如果向后台发送请求,频繁触发,对服务器造成不必要的压力
所以要==限制事件处理函数频繁调用==,就有两种方式可以做到,分别是函数节流和函数防抖
节流: 防抖:
# 2. 函数节流(throttle)
# Why
在页面中滚动鼠标滚轮,会触发scroll事件,而滚动一次会触发很多次!!!如果向后台发送请求,频繁触发,对服务器造成不必要的压力
window.addEventListener("scroll", function (e) {
console.log(e);
});
# How
通过设置一个时间间隔,使得函数在执行一次之后,超过时间间隔才会执行第二次
适合多次事件按照时间做平均分配触发
单位时间内,多次触发事件,只会有一次生效
# Where
resize
窗口调整
scroll
页面滚动
mousemove
DOM元素拖拽功能
click
疯狂点击
# throttle.js
创建一个节流函数,在 wait 毫秒内最多执行 callback
一次
/**
* 实现函数节流
* 功能: 创建一个节流函数,在 wait 毫秒内最多执行 `callback` 一次
* @param {*} callback
* @param {*} wait
* @returns
*/
export default function throttle(callback, wait) {
// 定义开始时间
let start = 0;
// 返回结果是一个函数
return function (e) {
// 获取当前时间戳
let now = Date.now();
// 判断
if (now - start >= wait) {
// 若满足条件,则执行回调函数【第一次会触发事件】
callback.call(this, e);
// 修改开始时间
start = now
}
}
}
这种方法,可以保证第一次一定被触发,后面就是间隔指定时间触发一次
还有一种写法
创建一个定时器 这种方法,第一次不会触发,要等到定时器到时间的才会触发
export default function throttle(callback, wait=100) {
let timer = null
return function () {
// 如果定时器开着在,就返回
if(timer) return
// 定时器回调执行结束了,重现开一个定时器
timer = setTimeout(() => {
callback.apply(this, arguments)
// 执行完回调,将定时器清空
timer = null
}, wait)
}
}
或者这样,创建一个 flag。 和上面的效果是一样的,因为使用的是箭头函数,所以不用指定this,自动找的就是外层的this
function throttle(callback, wait=100){
let flag = true
return function(){
if(flag){
flag = false
setTimeout(()=>{
flag = true
callback(...arguments)
}, wait)
}
}
}
# Demo
import throttle from "./function/throttle.js";
window.addEventListener(
"scroll",
throttle(function (e) {
console.log(e);
}, 500)
);
一次滚动只会执行一次函数
# 3. 函数防抖(debounce)
# How
在规定时间内,只让最后一次生效,前面的不生效。
适合多次事件一次响应的情况
多次连续触发相同的事件,只有最后一个生效
# Where
keyup/input
输入框实时搜索联想
在输入框输入内容时,每输入一个字符都会触发一次 keyup
let input = document.querySelector("input");
input.onkeydown = function (e) {
console.log(e.keyCode);
};
# debounce.js
/**
* 实现函数防抖
* 该函数会从上一次被调用后,延迟 wait 毫秒后调用 callback
* @param {*} callback
* @param {*} time
* @returns
*/
export default function debounce(callback, time) {
// 定时器变量
let timeId = undefined;
// 返回一个函数
return function () {
if (timeId !== undefined) {
// 清空定时器
clearTimeout(timeId);
}
// 启动定时器
timeId = setTimeout(() => {
// 执行回调
callback(...arguments);
// 执行完了重置id
timeId = undefined;
}, time);
};
}
# Demo
import debounce from "./function/debounce";
let input = document.querySelector("input");
input.onkeydown = debounce(function (e) {
console.log(e.keyCode);
}, 1000);
# 4. 区别
节流:多次事件按照时间做平均分配触发
防抖:多次事件一次响应的情况