这是我参与8月更文挑战的第25天,活动详情查看:8月更文挑战
是什么?
所谓防抖,就是指触发事件后在 n 秒内函数只能执行一次,如果在 n 秒内又触发了事件,则会重新计算函数执行时间。
防抖是优化高频率执行js代码的一种手段
你尽管触发事件,但是我一定在事件触发 n 秒后才执行,如果你在一个事件触发的 n 秒内又触发了这个事件,那我就以新的事件的时间为准,n 秒后才执行,总之,就是要等你触发完事件 n 秒内不再触发事件,我才执行。
为什么用?
在日常开发中,我们常常需要考虑很多用户有可能的操作,也需要经常考虑项目的性能问题。比如:有一个按钮,每次点击按钮之后,都会发起一个请求,这时,如果用户对这个按钮疯狂点击,就会极大地浪费资源,降低前端性能;又或者,我们有一个输入框,每输入一个字,都会发送请求给后端,后端返回匹配的人名,这个时候我们考虑性能的问题话,不必立马给后端发送请求,可以说让用户输入停止300ms后再次发送请求。这个时候,我们就可以考虑使用防抖了
怎么用?
在项目中,我们可能用得比较多lodash这个插件,他这个插件的防抖函数,也比较全面,可以立即执行,也可以延迟执行。
在vue项目中,我们会这么直接使用
import debounce from 'lodash/debounce';
methods: {
fn: debounce(function () {
// 执行操作
}, 200)
}
他还有第三个参数,是一个对象,里面有两个互斥的属性
leading&trailing
leading: 默认为false 为true时,代表延迟前执行
trailing: 默认为true,为true时,代表延迟后执行
实现
然后自己实现一个简单的吧
function debounce(fn,wait,options) {
let leading = false
if (isObject(options)) {
leading = !!options.leading
}
let timer, hasOperate
// 这边我返回的是箭头函数,所以不用新建一个this变量去接收
return (...args) => {
// clearTimeout之后,timer还是有值的
if(timer) clearTimeout(timer)
// 如果是立即执行的
if(leading) {
hasOperate = !timer
timer = setTimeout(() => {
timer = null
},wait)
// 如果执行过一次之后,hasOperate就变成了true,永远不会再执行了
if(hasOperate) fn.apply(this, args)
}else {
timer = setTimeout(() => {
// 用...args,那args就是一个数组
fn.apply(this, args)
},wait)
}
}
}
使用
<div>
<div id="button1">点击</div>
</div>
<script>
function isObject(value) {
const type = typeof value
return value != null && (type === 'object' || type === 'function')
}
const button1 = document.getElementById('button1')
function cl(e) {
console.log('e ', e);
return e
}
button1.addEventListener('click', debounce(cl,1000,{leading:true}))
</script>