MAC 上元素滑动时阻止页面后退
场景描述
mac 的chrome 中, 可以通过双指滑动触摸板, 实现滚动操作. 同时双指操作也可以触发浏览器的回退或向前. 因此在可以滑动的区域, 会先触发元素的滑动, 当已经滑动到头时, 会触发页面的回退操作. 该特性非常容易误操作导致页面回退. 如果有未保存的内容, 会严重影响用户体验 本文针对该问题介绍两种解决方法
如下图, 在元素内滑动时触发了页面回退
测试代码
可以参考该测试代码 codesandbox.io/s/scroll-pr…
html 结构
<div class="outside">
<div id="container">
<div class="inner">Test Scroll</div>
</div>
</div>
样式
#container {
width: 500px;
overflow: scroll;
border: 1px solid green;
}
.inner {
width: 800px;
height: 100px;
}
.outside {
width: 500px;
overflow: scroll;
}
.outside::-webkit-scrollbar {
-webkit-appearance: none;
display: none;
}
方法一 禁止默认事件
由于浏览器并未单独提供禁止页面回退的 API, 如果直接在 scroll 时阻止滚轮默认事件, 会导致滑动操作也无法触发.
因此需要通过 JS 判断当前滑动的位置, 当滑动到顶部后, 再禁止默认事件.
const container = document.getElementById("container");
// 监听滚轮事件
container.addEventListener("mousewheel", (event) => {
let delta = event.deltaX || event.wheelDeltaX;
// 上下滑动时不处理
if (!delta) {
return;
}
// 滚动到顶部或尾部时, 禁止默认事件
if (
(container.scrollLeft + container.offsetWidth === container.scrollWidth &&
delta > 0) ||
(container.scrollLeft === 0 && delta < 0)
) {
event.preventDefault();
}
});
方法二 在外层加一个元素, 使其无法滑动到顶部
页面回退操作是在滑动到顶部后, 再次滑动才会触发的. 因此可以使元素无法滑动到顶部, 则可以避免该情况的触发. 该方法思路是在滑动区域外部加一个元素, 使其永远无法滑动到顶部.
const outside = document.querySelector(".outside");
outside.addEventListener("scroll", (event) => {
if (outside.scrollLeft === 0) {
// 当滑到最左侧时, 设置 scrollLeft 为 1
outside.scrollLeft = 1;
} else if (outside.scrollLeft === outside.scrollWidth) {
// 当滑到最右侧时, 设置 scrollLeft 为 最大值 - 1
outside.scrollLeft = outside.scrollWidth - 1;
}
});