关键要点
本文由 Vildan Softic 和 Julian Motz 共同评审。感谢所有 SitePoint 的同行评审员,使 SitePoint 的内容达到最佳状态!
监听滚动事件的危险之一是性能下降。浏览器会在用户每次滚动时执行回调函数,这每秒可能会有很多事件。如果回调函数执行大量重绘操作,这对最终用户来说意味着坏消息。重绘代价高昂,尤其是在重绘视图的大部分内容时,例如发生滚动事件时的情况。
下面的示例说明了这个问题:
除了性能下降和容易引起癫痫发作之外。此示例说明了当计算机完全按照您的指示执行操作时会发生什么。背景颜色之间没有平滑的过渡,屏幕只是闪烁。任何不幸的程序员都可能觉得在这个世界上没有希望了。难道没有更好的方法吗?
规范事件
一种解决方案是推迟事件并一次管理多个事件。有两个常用的函数可以帮助我们做到这一点:节流和去抖。
节流保证在给定的时间间隔内事件的恒定流动,而去抖将一系列事件组合成单个事件。一种思考方式是节流是基于时间的,而去抖是基于事件的。节流保证执行,而去抖在分组发生后则不保证执行。如果您想了解具体信息,请查看这篇关于去抖与节流的深入讨论。
去抖
去抖解决的是不同的问题,例如带有 Ajax 的按键。当您在表单中键入内容时,为什么要为每个按键发送请求?更优雅的解决方案是将一系列按键组合成一个事件,该事件将触发 Ajax 请求。这符合键入的自然流程并节省了服务器资源。对于按键,事件之间的间隔并不重要,因为用户不会以恒定的速率键入。
节流
由于去抖没有保证,因此另一种方法是对滚动事件进行节流。滚动发生在给定的时间跨度内,因此进行节流是合适的。一旦用户开始滚动,我们希望保证及时执行。
此技术有助于检查我们是否位于页面的特定部分。鉴于页面的大小,滚动浏览内容需要很多秒。这使得节流能够仅在任何给定的间隔内触发一次事件。事件节流将使滚动体验更流畅并保证执行。
下面是使用原生 JavaScript 编写的简陋的事件节流器:
function throttle(fn, wait) { var time = Date.now(); return function() { if ((time + wait - Date.now()) < 0) { fn(); time = Date.now(); } } }
此实现设置一个时间变量,该变量跟踪函数第一次调用时的时刻。每次调用返回的函数时,它都会检查等待间隔是否已过去,如果已过去,则它会触发回调并重置时间。
使用库
事件节流有很多危险,不建议自己编写。与其编写自己的实现,我建议使用第三方实现。
lodash
lodash 是 JavaScript 中事件节流的事实上的标准。此库是开源的,因此您可以随意浏览代码。好处是该库是模块化的,因此可以从中获取所需的内容。
使用 lodash 的节流函数,滚动事件节流变得很简单:
window.addEventListener('scroll', _.throttle(callback, 1000));
这将传入的滚动事件洪流限制为每 1000 毫秒(一秒钟)一次。
API 提供了前沿和后沿选项,如下所示:
_.throttle(callback, 1, { trailing: true, leading: true });
这些选项确定回调函数是否在事件的前沿和/或后沿执行。
这里的一个问题是,如果您将前沿和后沿都设置为 false,则回调函数不会触发。将前沿设置为 true 将立即开始回调执行,然后进行节流。当您将前沿和后沿都设置为 true 时,这将保证每个间隔的执行。
从查看源代码中,我发现有趣的是 throttle() 只是 debounce() 的包装器。节流只是传递一组不同的参数来更改所需的行为。节流设置一个 maxWait,一旦等待这么长时间,它就会保证执行。其余的实现保持不变。
我希望您在下次事件节流冒险中发现 lodash 对您有益!
结论
节流与去抖的关键在于查看要解决问题的性质。这两种技术适用于不同的用例。我建议从用户的角度来看待问题以找到答案。
使用 lodash 的好处在于它在一个简单的 API 中抽象了大量复杂性。好消息是您可以在项目中使用 _.throttle()
,而无需添加整个库。有 lodash-cli,这是一个工具,可以让您只创建包含所需函数的自定义构建。事件节流只是整个库的一小部分。
关于节流滚动事件的常见问题解答 (FAQ)
在 JavaScript 中节流滚动事件是一种用于优化网站或 Web 应用程序性能的技术。当用户在网页上滚动时,浏览器会为每个像素的移动生成一个滚动事件。这可能导致每秒生成数百甚至数千个事件,这会严重降低网页的性能。通过节流这些事件,我们可以限制处理的事件数量,从而提高网页的性能和响应速度。
JavaScript 中的节流通过在事件执行之间设置延迟来工作。当触发事件时,计时器启动。如果在计时器结束之前触发另一个事件,则会忽略该事件。这确保了在处理另一个事件之前必须经过一定的时间量。此技术对于经常触发的事件(例如滚动事件)特别有用。
节流和去抖都是用于限制函数可以随时间执行次数的技术。两者之间的主要区别在于它们如何处理延迟。节流确保函数每 X 毫秒不会调用超过一次,而去抖确保函数直到自上次调用以来经过 X 毫秒后才会调用。换句话说,节流以规则的间隔执行函数,而去抖在一段时间不活动后执行函数。
可以使用 setTimeout
函数在 JavaScript 中实现节流。此函数允许您将函数的执行延迟指定的毫秒数。通过将 setTimeout
与事件侦听器结合使用,您可以确保事件处理程序函数每 X 毫秒不会调用超过一次。
是的,节流可以与 JavaScript 中的任何类型的事件一起使用,而不仅仅是滚动事件。它对于经常触发或需要大量处理的事件特别有用,例如鼠标移动事件、调整大小事件和按键事件。
是的,有几个库和框架提供对节流的内置支持。例如,流行的 JavaScript 实用程序库 Lodash 提供了一个节流函数,使实现节流变得容易。同样,流行的 JavaScript 库 jQuery 也在其 API 中提供了一个节流函数。
虽然节流可以提高网页的性能,但如果使用不当,它也可能导致用户体验响应速度较慢。例如,如果延迟设置得太高,用户可能会注意到他们的操作与网页的响应之间存在滞后。因此,在使用节流时,在性能和响应速度之间找到平衡非常重要。
您可以通过在实现节流之前和之后测量网页的性能来测试节流的有效性。这可以使用浏览器开发者工具来完成,该工具提供有关网页性能的详细信息,包括处理事件所需的时间。
是的,节流可以与其他性能优化技术结合使用,例如去抖和 requestAnimationFrame
。通过结合这些技术,您可以进一步提高网页的性能和响应速度。
是的,节流有几种替代方案,包括去抖和 requestAnimationFrame
。去抖类似于节流,但它不是限制函数可以随时间调用的次数,而是确保函数直到自上次调用以来经过一定时间后才会调用。requestAnimationFrame
是一种告诉浏览器执行动画并请求浏览器在下次重绘之前调用指定函数来更新动画的方法。
以上是快速提示:如何油门滚动事件的详细内容。更多信息请关注PHP中文网其他相关文章!