为什么防抖和节流?
我们使用窗口的 resize,scorll,mousemove,mousehover;输入框等校验时,如果事件处理函数调用无限制,会加剧浏览器的负担,尤其是执行了操作 DOM 的函数,那不仅造成计算资源的浪费,还会降低程序运行速度,甚至造成浏览的奔溃,影响用户体验。
防抖和节流有什么区别?
防抖:就是触发多次事件,最后一次执行事件处理函数。在事件被触发后,等待一段时间(例如100毫秒),如果在这段时间内没有再次触发事件,才执行相应的操作。如果在等待时间内又触发了事件,则重新计时等待时间。
节流:隔一段时间执行一次事件处理函数。在一定时间间隔内(例如每200毫秒),只允许事件执行一次。如果在这段时间内再次触发事件,忽略该事件,直到时间间隔过去,才允许下一次事件执行
防抖和节流有什么具体应用场景?
防抖:适用于那些在短时间内频繁触发事件的情况,比如输入框输入事件、窗口调整事件。防抖可以避免在用户还在输入过程中就立即执行操作,而是等待用户停止输入一段时间后再执行操作,减少频繁的操作执行。
节流:适用于那些需要限制事件触发频率的情况,比如滚动事件、鼠标移动事件、浏览器滚动监听事件。通过节流,可以确保在一定时间内只执行一次事件处理函数,避免过多的计算和操作。
防抖例子:
// 防抖函数 let deBounce = (fn, delay) => { let timer = null return function(...args) { if (timer) clearTimeout(timer) timer = setTimeout(() => { fn(...args) }, delay) } } let oInput = document.getElementsByTagName('input')[0] // 模拟请求 let ajax = message => { let json = { message } console.log(JSON.stringify(json)) } let doAjax = deBounce(ajax, 200) // 键盘弹起执行 oInput.addEventListener('keyup', e => { doAjax(e.target.value) })
节流例子:
/* * 连续点击只会1000执行一次btnClick函数 */ let obutton = document.getElementsByTagName('button')[0] // 如果用箭头函数,箭头函数没有arguments,也不能通过apply改变this指向 function btnClick() { console.log('我响应了') } /* 方法1: 定时器方式实现 缺点:第一次触发事件不会立即执行fn,需要等delay间隔过后才会执行 */ let throttle = (fn, delay) => { let flag = false return function(...args) { if (flag) return flag = true setTimeout(() => { fn(...args) flag = false }, delay) } } /* 方法2:时间戳方式实现 缺点:最后一次触发回调与前一次的触发回调的时间差小于delay,则最后一次触发事件不会执行回调 */ let throttle = (fn, delay) => { let _start = Date.now() return function(...args) { let _now = Date.now(), that = this if (_now - _start > delay) { fn.apply(that, args) start = Date.now() } } } // 方法3:时间戳与定时器结合 let throttle = (fn, delay) => { let _start = Date.now() return function(...args) { let _now = Date.now(), that = this, remainTime = delay - (_now - _start) if (remainTime <= 0) { fn.apply(that, args) } else { setTimeout(() => { fn.apply(that, args) }, remainTime) } } } /* 方法4:requestAnimationFrame实现 优点:由系统决定回调函数的执行机制,60Hz的刷新频率,每次刷新都会执行一次回调函数,不 会引起丢帧和卡顿 缺点:1.有兼容性问题2.时间间隔有系统决定 */ let throttle = (fn, delay) => { let flag return function(...args) { if (!flag) { requestAnimationFrame(function() { fn.apply(that, args) flag = false }) } flag = true } } obutton.onclick = throttle(btnClick, 1000)