防抖 防抖的目的就是防止帕金斯 防止频繁点击
// 最简单的防抖处理:加标识判断即可
let submit = document.querySelector('#submit');
submit.isLoading = false; //标识判断
submit.onclick = function () {
if (this.isLoading) return;
this.isLoading = true;
console.log('数据请求发送...');
setTimeout(() => {
console.log('数据请求成功');
this.isLoading = false;
}, 5000);
};
具备公共性的防抖函数处理:在用户频繁触发【频繁的规则自己设定】操作的场景中 我们只识别一次即可【识别第一次 识别最后一次】
规则 300ms内触发两次及以上,就算频繁操作
在接下来一直点5分钟 只识别一次 这就是属于频繁操作
一直点 过了3min后我不点了[在最后一次点击500ms内没有点] 识别一次
过了1s钟,我们又开始频繁点,这是下一次频繁操作 还可以在识别一次
思路
- 第一次点击:设置定时器 等待300ms
- 如果300ms没有点击第二次,属于非频繁触发,我们让handle执行一次
- 如果触发了第二次,属于频繁操作,首先先把上一个没到时间定时器干掉,自己在重新设置一个新的定时器,等待300ms
- 如果在这个时间内,再次点击,我们再把它干掉,再重新设置一个
关于清空定时器
timer是一个数字,记录当时定时器的编号 clearTimeout(timer):按照编号清除定时器【但是timer的值还是之前的数字】 所以我们一般把timer设置为null;这样做的好处:如果timer=null我们就知道没有定时器 如果不为null则认为定时器还没有清除
let timer = 10; timer = clearTimer(timer); console.log(timer);
const clearTimer = function clearTimer(timer) {
if (timer) clearTimeout(timer);
return null;
};
const debounce = function debounce(func, wait, immediate) {
if (typeof func !== 'function')
throw new TypeError('func is not a funciton');
if (typeof wait === 'boolean') immediate = wait;
if (typeof wait !== 'number') wait = 300;
if (typeof immediate !== 'boolean') immediate = false;
let timer = null;
return function operate(...params) {
let now = !timer && immediate,
result;
timer = clearTimer(timer);
timer = setTimeout(() => {
// 让方法执行的时候THIS是实参和没有debounce之前是一样的
// 最后执行【结束边界】
if (!immediate) func.call(this, ...params);
// 清除最后一次设定的定时器
timer = clearTimer(timer);
}, wait);
//立即执行:【开始边界】
if (now) result = func.call(this, ...params);
return result;
};
};
const handle = function handle() {
console.log('数据请求发送...');
setTimeout(() => {
console.log('数据请求成功');
this.isLoading = false;
}, 3000);
};
//submit.onclick = debounce(handle, 300);//func:handle wait:300 immediate:false
//submit.onclick = debounce(handle); //func:handle wait:300 immediate:false
//submit.onclick = debounce(handle, 300, true); //func:handle wait:300 immediate:true
//submit.onclick = debounce(handle, true); //func:handle wait:300 immediate:true
// submit.onclick=function operate(ev){
//疯狂点击按钮的时候,浏览器会疯狂的触发operate函数执行 我们只需要在operate中 控制handle只执行一次
//}
节流:控制触发的频率
一直点击5min,这样它会间隔500ms触发一次
/*
* throttle:函数节流
* @params
* func:自己最终要执行的任务
* wait:触发的频率「默认值:500ms」
* @return
* operate处理函数
*/
const throttle = function throttle(func, wait) {
if (typeof func !== "function") throw new TypeError('func must be an function!');
if (typeof wait !== "number") wait = 500;
let timer = null,
previous = 0;
return function operate(...params) {
let now = +new Date(),
remaining = wait - (now - previous),
result;
if (remaining <= 0) {
// 两次间隔时间超过500ms了,让方法立即执行
timer = clearTimer(timer);
result = func.call(this, ...params);
previous = +new Date();
} else if (!timer) {
// 没设置过定时器等待,则我们设置一个去等待即可
timer = setTimeout(() => {
timer = clearTimer(timer);
func.call(this, ...params);
previous = +new Date();
}, remaining);
}
return result;
};
};