为什么用防抖和节流函数?
在我们编写前端代码时经常会遇到某类高频操作,如:
用户输入框的模糊查询(监听输入调用接口)
window.onsize或window.onscroll的执行(判断当前窗口大小或当前视口高度等等)
如果不用防抖或节流函数约束函数执行频率,监听用户输入实时调用接口或监听窗口改变去执行一系列的dom操作;那么可想而知,对性能造成的影响有多大。
节流
效果:让高频的执行函数平滑的执行,一段时间内只执行一次。
使用场景:window.onsize 和 window.onscroll等高频执行的函数。
封装代码:
function throttle(fn, time) {
let timer = null;
return function (...arg) {
//上一次timer未执行 不创建定时器
if (!timer) {
timer = setTimeout(() => {
//如果有参数 call传递参数进去
fn.call(this, ...arg);
timer = null
}, time);
}
}
}
原理:利用闭包存储变量的方式,上一次执行创建定时器,下一次执行去查询上一次定时器已执行,没有就继续创建定时器,这样就保证fn函数在timer秒后延迟执行。
使用方法:
function handle(...args) {
console.log(Math.random(), new Date())
console.log(...args)
}
window.addEventListener("mousemove", throttle(handle, 1000))
让handle函数1s执行一次。
如图可以看见当鼠标在页面上移动,每隔1s会返回当前的鼠标指针位置。
防抖
效果:让高频的执行变为只执行最后一次。
使用场景:input每次输入都去执行函数,鼠标连续点击。
封装代码:
function debounce(fn, time) {
let timer = null;
return function (...arg) {
//上一次timer未执行 销毁定时器
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(() => {
//如果有参数 call传递参数进去
fn.call(this, ...arg)
}, time);
}
}
原理:使用闭包特性,每次都去销毁上一次的定时器,创建新的最后一次点击的定时器。
使用方法:
function handle(...args) {
console.log(...args)
}
const waitHandle = debounce(handle, 500);
document.getElementById("click").onclick = (...res) => {
waitHandle(...res)
}
当我点击ID为click(onclick按钮)的元素时,防抖函数会判断在500ms内是否点击了多次,当停止点击的时候会在500ms以后输出最后一次点击的内容。
如有错误,欢迎指出~~