「这是我参与11月更文挑战的第13天,活动详情查看:2021最后一次更文挑战」
前言
函数的防抖节流,目前我们前端很多项目都运行在浏览器下,那就有很多的人机交互的操作,那我们对按钮可以有很高频率的事件点击,那这样对浏览器有一定的性能消耗的
场景
- 滚动事件
- 输入的模糊匹配
- 轮播图切换
- 点击操作
- ...
浏览器默认情况下都会有总结的监听事件间隔(谷歌:4-6ms),如果监测到多次事件的监听执行,那么就会造成不必要的资源浪费
防抖
对于高频的操作来说,我们只希望识别一次点击,可以任务是第一次或者是最后一次
函数实现
/**
* handle 执行函数
* wait 事件触发之后多久开始执行
* immeadite 控制是第一次执行还是最后一次执行
*/
const obj = {
wait: 300,
immeadite: false
}
function myDebounce (handle, obj = obj) {
if(typeof handle !== 'function') {
throw new Error('必须传入方法')
}
if(!obj instanceof Object) {
throw new Error('请传入合适的参数')
}
let timer = null
return function proxy (...args) {
let self = this
let init = obj.immeadite && !timer
clearTimeout(timer)
timer = setTimeout(() =>{
timer = null
!obj.immeadite && handle.apply(self, args)
}, obj.wait)
// 如果当前传递进来的值 是 true, 那么就表示我们需要立即执行这个函数
// 如果需要实现在第一次执行,那么添加上 timer 为 null作为判断
// 因为只要 timer为 null 就以意味着没有第二次点击
init && handle.apply(self, args)
}
}
这里送上我的测试用代码:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type"
content="text/html; charset=utf-8">
<title>事件</title>
</head>
<body>
<button id="btn">计算</button>
<script>
var Btn = document.getElementById('btn');
const obj = {
wait: 300,
immeadite: false
}
function myDebounce(handle, obj = obj) {
if (typeof handle !== 'function') {
throw new Error('必须传入方法')
}
let isObject = Object.prototype.toString.call(obj) ==='[object Object]'
if (!isObject) {
throw new Error('请传入合适的参数')
}
let timer = null
return function proxy(...args) {
let self = this
let init = obj.immeadite && !timer
clearTimeout(timer)
timer = setTimeout(() => {
timer = null
!obj.immeadite && handle.apply(self, args)
}, obj.wait)
// 如果当前传递进来的值 是 true, 那么就表示我们需要立即执行这个函数
// 如果需要实现在第一次执行,那么添加上 timer 为 null作为判断
// 因为只要 timer为 null 就以意味着没有第二次点击
init && handle.apply(self, args)
}
}
function btnclick (a) {
console.log("push the button",a);
}
Btn.onclick = myDebounce(btnclick, {
wait: 3000,
immeadite: false
})
</script>
</body>
</html>