MAC 上元素滑动时阻止页面后退

2,145 阅读1分钟

MAC 上元素滑动时阻止页面后退

场景描述

mac 的chrome 中, 可以通过双指滑动触摸板, 实现滚动操作. 同时双指操作也可以触发浏览器的回退或向前. 因此在可以滑动的区域, 会先触发元素的滑动, 当已经滑动到头时, 会触发页面的回退操作. 该特性非常容易误操作导致页面回退. 如果有未保存的内容, 会严重影响用户体验 本文针对该问题介绍两种解决方法

如下图, 在元素内滑动时触发了页面回退 2022-09-04-03-49-02.png

测试代码

可以参考该测试代码 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;
  }
});