1.防抖:
。原理:在事件被触发N秒以后在执行回调,如果在这N秒之内再次触发,则重新计算。
。使用场景:
。按钮提交场景:防止多次提交按钮,只执行最后一次。
。搜索框联想场景:防止连续发送请求,只发送N秒后的最后一次。
简易版实现
const btnEle = document.querySelector(".btn");
btnEle.onclick = debounce(function () { console.log("我执行了最后一次")}, 3000)
//防抖函数
//创建一个函数:接受一个执行函数,多少秒执行
function debounce(func, wait) {
console.log("第一次执行");
//定义有效时间
let timeout;
return function () {
console.log("我被点击了1。")
//获取当前对象
const context = this;
// 当前参数
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function () {
func.apply(context, args);
}, wait)
}
。立即执行版本
const btnEle = document.querySelector(".btn");
btnEle.onclick = debounce(function () { console.log(123) }, 3000, true);
//有时候需要立即执行,然后等到停止触发N秒后,才可以重新触发
/*
fn: 回调函数
wait:多少秒后执行
immediate:立即执行(true/false)
*/
function debounce(fn, wait, immediate) {
//加载执行
let timeOut;
return function () {
const context = this;
const args = arguments;
if (timeOut) clearTimeout(timeOut);
if (immediate) {
const callNow = !timeOut;
timeOut = setTimeout(function () {
console.log("我执行完了")
timeOut=null;
}, wait)
if (callNow) fn.apply(context, args);
} else {
timeOut = setTimeout(function () {
fn.apply(context, args);
}, wait)
}
}
。返回值版实现
。func函数可能会有返回值,所以需要返回函数结果,但是 immediate 为false 的时候,因为使用setTimeout,我们将func.apply(context,args)
值赋值给变量,最后再retrue的时候,值将会一直是undefined,所以只在immediate为true的时候直接返回函数的执行结构
function debounce(fn, wait, immediate) {
let timeOut, result;
return function () {
let context = this;
let args = arguments;
if (timeOut) clearTimeout(timeOut);
if (immediate) {
let callNow = !timeOut;
timeOut = setTimeout(() => {
timeOut = null;
}, wait);
if (callNow) result= fn.apply(context, args);
} else {
timeOut = setTimeout(() => {
result= fn.apply(context, args);
}, wait);
}
console.log(result);
}
2.节流
。原理:规定单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
。使用场景
拖拽场景,固定时间内只执行一次,防止超高频次触发位置变动。
缩放场景,监控浏览器resize。
。使用时间戳实现
。使用时间戳,当触发事件的时候,我们取出当前的时间戳,然后减去之前的时间戳(最一开的初始值为0),如果
大于设置时间周期,就执行函数,然后更新时间戳为当前的时间戳,如果小于,就不执行。
function throttle(fn, wait) {
let context, args;
let prvious = 0;
return function () {
let now = +new Date();
let context = this;
let args = arguments;
if (now - prvious > wait) {
fn.apply(context, args);
prvious = now;
}
}
}
。使用定时器实现
。当触发事件的时候,我们设置一个定时器,再触发事件的时候,如果定时器存在,就不执行,
直到定时器执行,然后执行函数,清空定时器,这样可以设置下个定时器。
function throttle(fn, awit) {
let timeOut;
return function () {
const context = this;
const args = arguments;
if (!timeOut) {
timeOut = setTimeout(() => {
timeOut = null;
fn.apply(context, args);
}, awit)
}
}
}
原文:https://www.cnblogs.com/James-net/p/13949085.html