scroll
和 wheel
都是滚动事件,有啥差别呢?
scroll
:元素滚动时触发的事件wheel
:用户滚动鼠标滚轮或类似的输入设备时触发的事件
触发条件
滚轮滚动或触控板滑动
- 能触发
scroll
和wheel
事件,wheel
先触发,scroll
后触发 - 滚动条到达起始点或者终点之后,
wheel
依然触发,而scroll
不再触发
滚动条拖动
只能触发 scroll
,不能触发 wheel
键盘按键
- 向下或向上按键(每次修改
scrollTop
的大小为 40) - 空格或 Shift + 空格
- PageDown 或 PageUp
都会触发 scroll
事件,而不会触发 wheel
事件
其他
- 修改
scrollTop
、scrollLeft
等都会触发scroll
事件,而不会触发wheel
事件(即使容器的overflow: hidden;
) - 容器的
overflow: hidden;
进行滚轮操作,会触发wheel
事件,不会触发scroll
事件
判断方向
- 通过
wheel
事件的deltaY
来判断滚动方向,正数向下,负数向上 - 推荐使用
scroll
事件前后的scrollTop
的差值来判断方向
阻止冒泡
本身不存在滚动事件冒泡的说法,scroll
和 wheel
事件触发时,都不会冒泡(就像 focus
和 blur
)
但是当滚动条达到某一个顶点时,再次通过触发 wheel
事件的方式,会让最近的可滚动父元素触发 scroll
事件
而在此研究的便是防止子元素触发的 wheel
事件,影响到父元素,导致父元素发生 scroll
实现:可以通过在 wheel
事件上设置 preventDefault
和 stopPropagation
来阻止子元素的影响父元素(必须两者都设置才能生效)
阻止滚动
不能通过在 scroll
监听器中使用 event.preventDefault()
来阻止滚动,因为它在滚动之后才触发
应该:
- 阻止
wheel
:防止鼠标滚动 - 阻止
keydown
:防止键盘的 PageDown、PageUp 等键 - 隐藏滚动条:防止拖动滚动条
当然,最好的方法应该是设置 CSS 的 overflow: hidden
应用场景
简单来说,scroll
事件比较合适应用于有实际滚动条存在的场景;反之则使用 wheel
事件
如:需要自己在滚动过程中实现元素的吸顶或者吸底,那就使用 scroll
事件,虚拟列表
如:因一些特殊原因,原生的滚动条不能满足业务场景,则只能自己模拟实现满足业务的滚动条,那就使用 overflow: hidden
+ wheel
事件,平滑滚动