本文转载自微信公众号「新钛云服」,作者方章和。转载本文请联系新钛云服公众号。
在平时的编码过程中,当绐浏览器注册一个时间,经常会遇到一些执行次数非常频繁的事件,如scroll,resize等,事件频繁的执行会导致浏览器进行大量的计算而引发页面卡顿假死的情况,为些我们需要通过一些手段来解决这个问题,所以就有了防抖和节流这两个技术。
事件节流 throttle
是指在某段时间内,不管你触发了多少次回调事件,我都只认第一次,并在计时结束时给予响应,至于后面你再触发多少次回调我都不会予以回应。代码实现如下:
- // fn执行的函数, interval是时间间隔的阈值, 意为多久后执行,单位毫秒
- function throttle(fn, interval) {
- // 上一次触发回调的时间
- let last = 0
- return function () {
- let context = this
- let args = arguments
- let now = +new Date()
- // 判断上次触发的时间和本次触发的时间差是否小于设置的间隔时间
- if (now - last >= interval) {
- // 如果时间间隔大于我们设定的时间间隔阈值,则执行回调
- last = now;
- fn.apply(context, args);
- }
- }
- }
- // 绐scroll事件增加节流
- const newScroll = throttle(() => console.log('滚动了'), 1000)
- document.addEventListener('scroll', newScroll)
事件防抖Debounce
与事件节流怡好相反,事件防抖只认最后一次,不管你前面触发了多少次我都不管,我只执行你最后一次触发事件的回调,代码实现如下:
- // fn执行的函数, delay是延迟多久执行的时间, 意为多久后才触发事件,单位毫秒
- function debounce(fn, delay) {
- let timer = null
- return function () {
- let context = this
- let args = arguments
- // 每次事件被触发时,都去清除之前的旧定时器
- if(timer) {
- clearTimeout(timer)
- }
- timer = setTimeout(function () {
- fn.apply(context, args)
- }, delay)
- }
- }
- const newScroll = debounce(() => console.log('滚动了'), 1000)
- document.addEventListener('scroll', newScroll)
函数防抖的应用场景
连续的事件,只需触发一次回调的场景有:
搜索框搜索输入。只需用户最后一次输入完,再发送请求
手机号、邮箱验证输入检测
窗口大小Resize。只需窗口调整完成后,计算窗口大小。防止重复渲染。
函数节流的应用场景
间隔一段时间执行一次回调的场景有:
- 滚动加载,加载更多或滚到底部监听
- 百度搜索框,搜索联想功能
- 高频点击提交,表单重复提交