快速提示:如何节流滚动事件

卡米洛·雷耶斯
分享

本文由Vildan Softic而且朱利安Motz.感谢所有SitePoint的同行审必威西盟体育网页登录稿人,让SitePoint的内容成为最好的!

监听滚动事件的危险之一是性能下降。浏览器将每次执行回调用户滚动的时间,可以是每秒多个事件。如果回调执行了大量的重绘,这对最终用户来说意味着坏消息。重绘是昂贵的,特别是当您重绘视图的大部分时,例如当出现滚动事件时。

下面的例子说明了这个问题:

看钢笔未节流滚动事件由Si必威西盟体育网页登录tePoint (@必威西盟体育网页登录SitePoint)CodePen

除了性能下降和容易引起癫痫。这个例子说明了当计算机完全按照你的要求去做时会发生什么。背景颜色之间没有平滑的过渡,屏幕只是闪烁。任何不幸的程序员都会觉得这个世界上已经没有希望了。难道没有更好的办法吗?

调节活动

一种解决方案是推迟事件并同时管理一堆事件。有两个常用的函数可以帮助我们做到这一点:throttle和debounce。

Throttle保证在给定的时间间隔内恒定的事件流,而debounce则将一系列事件分组为单个事件。一种方法是,节流是基于时间的,反弹是事件驱动的。节流保证执行,而一旦分组发生,debounce就不执行了。如果你想知道细节,看看这个深入讨论反弹与节流

防反跳

Debounce解决了一个不同的问题,比如使用Ajax的按键。当您输入表单时,为什么每次击键都要发送一个请求?更优雅的解决方案是将一连串的击键组合成一个事件,该事件将触发Ajax请求。这符合自然的输入流程并节省服务器资源。对于按键,事件之间的间隔并不重要,因为用户不会以恒定的速率输入。

节气门

由于debounce没有保证,替代方法是限制滚动事件。滚动发生在一个给定的时间范围内,所以它是合适的节流。一旦用户开始滚动,我们希望保证及时执行。

这种技术有助于检查我们是否在页面的特定部分。考虑到页面的大小,滚动内容需要花费许多秒。这使得节流在任何给定的时间间隔内只触发一次事件。事件节流将使滚动体验更流畅,并保证执行。

下面是一个用JavaScript编写的穷人事件节流器:

函数节气门fn等待var时间日期现在返回函数如果时间+等待-日期现在<0fn时间日期现在

此实现设置一个时间变量,它跟踪函数第一次调用的时间。每次调用返回的函数时,它都会检查等待Interval已经过,如果是,它将触发回调并重置时间

看钢笔Vanilla JS节流阀实现由Si必威西盟体育网页登录tePoint (@必威西盟体育网页登录SitePoint)CodePen

使用图书馆

事件节流有很多危险,不建议在内部自行设计。与其编写自己的实现,我建议使用第三方实现。

lodash

lodash是JavaScript中事件节流的事实标准。这个库是开源的,所以请随意探索代码。好的是这个库是模块化的,所以你可以从中获取你需要的东西。

使用lodash的滚动事件节流变得简单节气门功能:

窗口addEventListener“滚动”_节气门回调1000

这将传入滚动事件的混乱限制为每1000毫秒(1秒)一次。

API提供了一个领先的而且落后于选项如下:

_节气门回调1落后于真正的领先的真正的

这些选项决定是否在前缘和/或后缘执行回调。

这里的一个问题是,如果您指定前导和尾集为,回调不触发。将引线设置为真正的将立即开始回调执行,然后节流。当你设置前导和后尾为时真正的,这保证了每个间隔执行一次。

在CodePen上查看演示:节流滚动事件

通过查看源代码,我发现有趣的是节流()只是一个包装防反跳().节流只是传递一组不同的参数来更改所需的行为。节流设置maxWait这保证了等待那么长时间后的执行。实现的其余部分保持不变。

我希望你发现lodash在你的下一个事件节流冒险有益!

结论

节流和反弹的关键是看你要解决的问题的性质。这两种技术适用于不同的用例。我的建议是从用户的角度看问题,找到答案。

使用lodash的美妙之处在于它在一个简单的API中抽象了大量的复杂性。好消息是你可以使用_.throttle ()在您的项目中,而不必添加整个库。有lodash-cli,该工具允许您仅使用所需的功能创建自定义构建。事件节流只是整个库的一小部分。

Baidu