tua-body-scroll-lock
解决模态窗滑动时候,穿透到背景,背景被滑动的问题
示例:使用的 vue
1 | import { lock, unlock } from "tua-body-scroll-lock"; |
看一下 tua-body-scroll-lock 库做了什么
首先是 lock 方法
1 | const lock = (targetElement?: HTMLElement) => { |
看一下 unlock 方法
1 | const unlock = (targetElement?: HTMLElement) => { |
问题产生的原因
滚动穿透不是浏览器的 bug。我们在页面上加了一个遮罩层并不会影响 document 滚动事件的产生。也就是说遮罩层虽然不可滚动,但是这个时候浏览器会去触发 document 的滚动从而导致了下方文档的滚动。也就是说如果 document 也不可滚动了,也就不会有这个问题了。
简述 tua-body-scroll-lock 中的实现方式
ios
- 禁止 document 默认行为
1 | document.addEventListener( |
- 模态窗内还需要可滑动的元素,需要阻止其冒泡(如果没有阻止冒泡会触发到 document 的 touchmove,之后被禁止默认行为,导致页面无法滚动)
1 | target.ontouchmove = function (event) { |
满足上面 2 个条件以后,虽然可以禁止背景滚动,但是当模态窗内容区域滑动到底部、或者顶部的时候,还是可以导致背景滑动。
- 所以还得在内容区域里的内容滚动到底部或者顶部的时候,就禁止默认行为
1 | target.ontouchmove = function (event) { |
安卓
给 body 和 html 加样式,超出隐藏,并且在 unlock 的时候,主动滚动到之前的位置
1 | var setOverflowHiddenMobile = function setOverflowHiddenMobile() { |
##参考资料
Unable to preventDefault inside passive event listener due to target being treated as passive 报错
翻译一下:chrome 监听 touch 类事件报错:无法被动侦听事件 preventDefault,是新版本 chrome 浏览器报错。
说明:说一下这个 preventDefault()是个什么鬼,这个是取消默认事件的,如果这个函数起作用的,比如默认的表单提交,a 链接的点击跳转,就不好用了。
原因:google 浏览器为了最快速的相应 touch 事件,做出的改变。
历史:当浏览器首先对默认的事件进行响应的时候,要检查一下是否进行了默认事件的取消。这样就在响应滑动操作之前有那么一丝丝的耽误时间。
现在:google 就决定默认取消了对这个事件的检查,默认时间就取消了。直接执行滑动操作。这样就更加的顺滑了。
解决方案:
1、注册处理函数时,用如下方式,明确声明为不是被动的
window.addEventListener(‘touchmove’, func, { passive: false })
2、应用 CSS 属性 touch-action: none; 这样任何触摸事件都不会产生默认行为,但是 touch 事件照样触发。
touch-action 还有很多选项,