博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
防抖(Debouncing)和节流(Throttling)
阅读量:5026 次
发布时间:2019-06-12

本文共 2734 字,大约阅读时间需要 9 分钟。

onscoll防抖封装函数

scroll 事件本身会触发页面的重新渲染,同时 scroll 事件的 handler 又会被高频度的触发, 因此事件的 handler 内部不应该有复杂操作,例如 DOM 操作就不应该放在事件处理中。

 

针对此类高频度触发事件问题(例如页面 scroll ,屏幕 resize,监听用户输入等),下面介绍两种常用的解决方法,防抖和节流。

 

防抖(Debouncing)

 

防抖技术即是可以把多个顺序地调用合并成一次,也就是在一定时间内,规定事件被触发的次数。

 

通俗一点来说,看看下面这个简化的例子:

// 防抖动函数function debounce(func, wait, immediate) {    var timeout;    return function() {        var context = this, args = arguments;        var later = function() {            timeout = null;            if (!immediate) func.apply(context, args);        };        var callNow = immediate & !timeout;        clearTimeout(timeout);        timeout = setTimeout(later, wait);        if (callNow) func.apply(context, args);    };}; var myEfficientFn = debounce(function() {    // 滚动中的真正的操作}, 250);

节流(Throttling)

 

防抖函数确实不错,但是也存在问题,譬如图片的懒加载,我希望在下滑过程中图片不断的被加载出来,而不是只有当我停止下滑时候,图片才被加载出来。又或者下滑时候的数据的 ajax 请求加载也是同理。

 

这个时候,我们希望即使页面在不断被滚动,但是滚动 handler 也可以以一定的频率被触发(譬如 250ms 触发一次),这类场景,就要用到另一种技巧,称为节流函数(throttling)。

 

节流函数,只允许一个函数在 X 毫秒内执行一次。

 

与防抖相比,节流函数最主要的不同在于它保证在 X 毫秒内至少执行一次我们希望触发的事件 handler。

 

与防抖相比,节流函数多了一个 mustRun 属性,代表 mustRun 毫秒内,必然会触发一次 handler ,同样是利用定时器,看看简单的示例:

// 简单的节流函数function throttle(func, wait, mustRun) {    var timeout,        startTime = new Date();    return function() {        var context = this,            args = arguments,            curTime = new Date();        clearTimeout(timeout);        // 如果达到了规定的触发时间间隔,触发 handler        if(curTime - startTime >= mustRun){            func.apply(context,args);            startTime = curTime;        // 没达到触发间隔,重新设定定时器        }else{            timeout = setTimeout(func, wait);        }    };};// 实际想绑定在 scroll 事件上的 handlerfunction realFunc(){    console.log("Success");}// 采用了节流函数window.addEventListener('scroll',throttle(realFunc,500,1000));

上面简单的节流函数的例子可以拿到浏览器下试一下,大概功能就是如果在一段时间内 scroll 触发的间隔一直短于 500ms ,那么能保证事件我们希望调用的 handler 至少在 1000ms 内会触发一次。

 

使用 rAF(requestAnimationFrame)触发滚动事件

 

上面介绍的抖动与节流实现的方式都是借助了定时器 setTimeout ,但是如果页面只需要兼容高版本浏览器或应用在移动端,又或者页面需要追求高精度的效果,那么可以使用浏览器的原生方法 rAF(requestAnimationFrame)。

 

window.requestAnimationFrame() 这个方法是用来在页面重绘之前,通知浏览器调用一个指定的函数。这个方法接受一个函数为参,该函数会在重绘前调用。

 

rAF 常用于 web 动画的制作,用于准确控制页面的帧刷新渲染,让动画效果更加流畅,当然它的作用不仅仅局限于动画制作,我们可以利用它的特性将它视为一个定时器。(当然它不是定时器)

 

通常来说,rAF 被调用的频率是每秒 60 次,也就是 1000/60 ,触发频率大概是 16.7ms 。(当执行复杂操作时,当它发现无法维持 60fps 的频率时,它会把频率降低到 30fps 来保持帧数的稳定。)

 

简单而言,使用 requestAnimationFrame 来触发滚动事件,相当于上面的:

 

throttle(func, xx, 1000/60) //xx 代表 xx ms内不会重复触发事件

简单的示例如下:var ticking = false; // rAF 触发锁function onScroll(){  if(!ticking) {    requestAnimationFrame(realFunc);    ticking = true;  }}function realFunc(){    // do something...    console.log("Success");    ticking = false;}// 滚动事件监听window.addEventListener('scroll', onScroll, false);

 

转载于:https://www.cnblogs.com/djdliu/p/5733078.html

你可能感兴趣的文章
SpringBoot 集成ehcache
查看>>
初步swift语言学习笔记2(可选类型?和隐式可选类型!)
查看>>
Nginx + Tomcat 反向代理 如何在高效的在一台服务器部署多个站点
查看>>
在Vs2012 中使用SQL Server 2012 Express LocalDB打开Sqlserver2012数据库
查看>>
在Macos下完美解决Adobe Dreamweaver CC 2018 汉化及操作方法
查看>>
【转】 Newtonsoft.Json高级用法
查看>>
CodeBlocks X64 SVN 编译版
查看>>
Excel催化剂开源第42波-与金融大数据TuShare对接实现零门槛零代码获取数据
查看>>
bug记录_signalr执行$.connnection.testhub结果为空
查看>>
【转】常用的latex宏包
查看>>
[TMS320C674x] 一、GPIO认识
查看>>
酷狗的皮肤文件存放在哪
查看>>
iOS RunLoop简介
查看>>
C++的引用
查看>>
T-SQL查询进阶--深入浅出视图
查看>>
MapKeyboard 键盘按键映射 机械革命S1 Pro-02
查看>>
Android读取url图片保存及文件读取
查看>>
完整ASP.Net Excel导入
查看>>
判断CPU大小端示例代码
查看>>
ARTS打卡第13周
查看>>