阅读 309

JS DOM编程笔记 - 滚动事件(十八)

今天我们来学习如何在JavaScript中处理滚动事件,如何优化滚动事件的性能。

滚动事件简介

当我们滚动页面或者在某个元素上滚动时就会触发滚动事件,我们可以通过以下方式触发滚动事件

  • 使用右侧滚动条

  • 使用鼠标滚轮

  • 点击锚点链接

  • 调用JS函数

要监听滚动事件,使用addEventListener()方法,事件名称为scroll,代码如下:

targetElement.addEventListener('scroll', (event) => {   // 处理滚动事件 }); 复制代码

或者给目标元素的onscroll属性绑定事件处理函数

targetElement.onscroll = (event) => {   // 处理滚动事件 }; 复制代码

监听整个网页滚动

要监听整个网页的滚动,我们给window对象来绑定scroll事件。

下面的例子展示了scroll事件的绑定方式:

<div style="height: 6000px;">   很高很高很高的元素 </div> <script>   window.addEventListener('scroll',(event) => {     console.log('滚动...');   }); </script> 复制代码

当我们滚动页面时,可以发现scroll事件处理函数一直在触发,控制台一直在打印 ''滚动...",直到我们停止滚动。

或者给window对象的onscroll属性绑定事件处理程序。

window.onscroll = function(event) {   console.log('滚动...'); }; 复制代码

注意:window 对象的 onscroll 属性与 document.body.onscroll 相同,可以将它们互换使用

document.body.onscroll = null; console.log(window.onscroll); // null 复制代码

滚动偏移量

window 对象有两个与滚动事件相关的属性:scrollXscrollY

scrollXscrollY 属性返回当前页面水平和垂直滚动的像素数。 scrollXscrollY 是双精度浮点值,如果需要整数值,可以使用 Math.round()将它们四舍五入。

如果文档根本没有滚动,则 scrollXscrollY 为 0。

pageXOffsetpageYOffsetscrollXscrollY 属性的别名。

请看下面的例子:

<div style="width: 3000px; height: 6000px;">   很高很高很高的元素 </div> <script>   window.addEventListener('scroll',(event) => {     console.log(window.scrollX, window.scrollY)   }); </script> 复制代码

监听元素滚动

window对象一样,我们可以给任何元素绑定scroll事件,但要获取元素的滚动偏移量要使用scrollTopscrollLeft 而不是 scrollXscrollY

使用scrollTop 属性可以设置或获取元素内容垂直滚动的像素数, scrollLeft 属性获取或设置元素内容从其左边缘滚动的像素数。

下面例子我们将通过scrollLeftscrollTop来去设置元素的滚动偏移量:

<!DOCTYPE html> <html> <head>   <title>JS scroll 滚动事件</title>   <style>     #scrollDemo {       height: 200px;       width: 200px;       overflow: auto;       background-color: #f0db4f     }     #scrollDemo p {       /* 展示滚动条 */       height: 300px;       width: 300px;     }   </style> </head> <body>   <div id="scrollDemo">     <p>JS scroll 事件示例</p>   </div>   <div id="control">     <button id="btnScrollLeft">Scroll Left</button>     <button id="btnScrollTop">Scroll Top</button>   </div>   <script>     let control = document.querySelector('#control');     control.addEventListener('click', function (e) {       // 获取滚动容器元素       let div = document.getElementById('scrollDemo');       // 获取点击的目标元素       let target = e.target;       // 处理每个按钮的行为       switch (target.id) {         case 'btnScrollLeft':           div.scrollLeft += 20;           break;         case 'btnScrollTop':           div.scrollTop += 20;           break;       }     });   </script> </body> </html> 复制代码

Kapture 2021-11-03 at 13.51.53

优化处理滚动事件

当我滚动页面或者元素时会触发很多次滚动事件,如果在事件处理程序内需要处理很多逻辑,那么每次代码都会花费时间来执行,这将导致页面滚动产生卡顿。

事件节流

我们最好不要在滚动事件处理程序内处理复杂的逻辑操作,并且去设置间隔多长时间去执行一次处理处理程序。

错误示例:

window.onscroll = () => {   // 处理逻辑 }; 复制代码

正确做法:

<div style="height: 6000px;">   很高很高很高的元素 </div> <script>   let scrolling = false;   window.onscroll = () => {     scrolling = true;   };   setInterval(() => {     if (scrolling) {       scrolling = false;       // 处理逻辑       console.log('滚动...')     }   },300); </script> 复制代码

你可能会奇怪,上面代码如何工作?

  • 首先,定义了scrolling变量,表示当前页面是否在滚动,在滚动事件处理程序中修改其值为true

  • 然后,如果滚动事件正在触发,则每 300 毫秒使用 setInterval()执行滚动事件处理程序。

这种处理方式被称为节流,因为从每秒执行N次到每 300 毫秒执行1次事件处理程序,大大减少了事件处理程序的执行次数。

Passive Event

最近几年,现代浏览器支持了Passive Event对于scroll, touchstart, wheel等事件支持。它允许 UI 线程在将控制权交给自定义事件处理程序之前立即处理事件。

下面是Chrome 官方的视频介绍:点击查看视频。

在支持Passive Event的 Web 浏览器中,需要将带有passive属性的对象传入到任何不调用 preventDefault() 的事件侦听器中,如下所示:

document.addEventListener(   'scroll',   (event) => {     // 处理逻辑   },    { passive: true } ); 复制代码

如果没有Passive Event,事件处理程序中的代码将始终在 UI 线程执行滚动之前被调用。

简单点来说,加了passive属性,浏览器就知道了不用再去等待事件处理函数执行完毕再去进行滚动,而是页面先滚动完成,之后再去执行事件处理函数。这样就不会产生由于事件绑定的问题,造成页面滚动产生卡顿。

它的兼容性如何:点击查看Can IUse。

image-20211103173715575

总结

  • 当滚动网页或元素时会触发 scroll 事件

  • window对象的scrollXscrollY 属性返回当前页面水平和垂直滚动的像素数。

  • 使用元素的scrollTopscrollLeft 属性设置或获取元素垂直滚动和从其左边缘滚动的像素数。

  • 使用事件节流来优化滚动事件性能。 在现代 Web 浏览器中,也可以使用Passive Event


作者:小帅的编程笔记
链接:https://juejin.cn/post/7026337573135974431


文章分类
代码人生
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐