1. 前言
在实际的开发过程中,会遇到一些高频触发的事件,比如输入框的模糊匹配,输入框的搜索,轮播图的点击,回到顶部功能,改变窗口的resize等等,对于这些高频事件场景,可以使用防抖和节流减少事件触发次数。
2. 防抖
防抖:防止手抖(短时间内多次触发),忽略前面的触发,等手不抖了,只触发最后一次(也可以只触发第一次,忽略最后一次) 场景:输入框输入搜索 原理:如果两次触发的间隔时间小于我们定义的间隔时间(wait),忽略上一次触发,以下一次触发为准,即可以使用定时器延时执行触发,每次触发重置定时器
<div id="app"></div>
<button id='btn'>点击</button>
</body>
<script>
var btn = document.getElementById('btn')
function handler () {
console.log('点击触发了')
}
btn.addEventListener('click', handler)
</script>
此时每次点击按钮都会触发handler事件,此时我们可以自己封装一个防抖函数,去让事件延迟触发
function handler () {
console.log('点击触发了')
}
btn.addEventListener('click', debounce(handler, 300))
function debounce (fn, wait) {
// 参数容错处理
if (typeof fn != 'function') throw new Error('first paramter must be a function')
wait = wait || 300
// 利用闭包定义一个计时器的初始值
let timer = null
// 每次点击实际触发的是handleClick函数
return function handleClick (...args) {
let self = this
// 又一次触发handleClick时,如果定时器存在,需要清除定时器,重新开始计时
if (timer) {
clearTimeout(timer)
}
// 如果没有定时器,则定义一个定时器,如果后续没有再次触发handlerClick,传入的fn就会执行
timer = setTimeout(() => {
fn.apply(self, args)
}, wait)
}
}
3. 节流
含义:顾名思义,开源节流,不是不执行,是减少频率的执行。可以理解为游戏里面的技能cd,在cd没有好的时候无论玩家怎么触发都不会执行。 场景:改变浏览器大小时触发的resize事件。 原理:事件触发后,指定的时间内不会再次触发事件,可以使用定时器,也可以使用时间差来处理。
body {height: 5000px; }
</style>
<script>
function scroll () {
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
console.log('滚动位置:' + scrollTop)
}
window.onscroll = scroll
此时浏览器每次滚动都会多次触发scroll事件,可以使用节流减少触发次数
var scrollTop = document.documentElement.scrollTop || document.body.scrollTop
console.log('滚动位置:' + scrollTop)
}
window.onscroll = throttle (scroll, 400)
function throttle (fn, wait) {
if (typeof fn != 'function') throw new Error ('must be a function')
wait = wait || 300
let cd = true
// 滚动滚动条,实际上执行的是handleScroll函数
return function handleScroll (...args) {
let self = this
// 如果技能cd没好,直接返回
if (!cd) return;
cd = false
setTimeout(() => {
fn.apply(self, args)
cd = true
}, wait)
}
}