详解滑动穿透(锁body)终极探索


Posted in Javascript onApril 16, 2019

场景

当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。

详解滑动穿透(锁body)终极探索

如图所示,浮层下边的内容并没有如想象中不受影响。

解决

先去github上搜索一番,发现有解决此问题的开源包,简单粗暴直接挑选了其中star的最高的(body-scroll-lock)操作一番!
使用后发现有一些问题:

  1. 安卓端全挂
  2. ios端偶尔会有锁不住的情况

查源码发现该包在iOS端使用禁止touchmove的方式单独处理,但是在其他端只是给body加overflow: hidden简单处理。
于是决定写一个针对多端通用的包来处理类似的问题。

 探索一:overflow: hidden

看到下边的滚动肯定立刻就想到了是整个viewport的滚动,那么如果给body设置overflow: hidden,此时body的内容就只有一屏了,肯定不会滚动了;

body { overflow: hidden; }

此方案在pc端完美解决了我们的问题,然而事情并没有那么简单;

再试试移动端:

详解滑动穿透(锁body)终极探索

移动端中并没有出现期待的效果。。。

既然pc端已经有了完美的方案,下边我们继续探索移动端的解决方案。

探索二:body定位

上边想到给body设置overflow: hidden在移动端并不能解决我们的问题,是否在于body的height没有设置

  1. 将html、body的高度都设置为100%;
  2. 给body设置绝对定位(fixed);

同时使用这两个操作似乎完美满足了我们的需求;

详解滑动穿透(锁body)终极探索

但是如图所示,每次都会将页面拉到最顶上的位置,这样看起来又不完美了;

既然使用了定位,那么给一个top值不就定位到我们想要的位置了(聪明如我)。

tips: body 设置 relative 定位会页面自身拉上去,下边留白

多次实验发现这个方案在android端中完美达到了我们想要的结果,但是在ios端并不理想;每次定位的时候会有闪动的问题;好事多磨,接着探索ios端的方案。

探索三:禁止touchmove

如果禁止掉页面的touchmove是否可行呢?话不多说就是干!
当弹出浮层的时候禁掉页面元素的touchmove

document.addEventListener('touchmove', function (event) {
  event.preventDefault()
})

测试发现没有达到想象中的效果,感觉这个结果并不能接受啊,禁止document 的touchmove都不能禁止滚动的吗?
进一步的探索后发现原因竟是这个属性

passive addEventListener第三个参数中传入

原来是浏览器做的一些优化,chrome passive-event-listeners
Passive Event Listeners是Chrome提出的一个新的浏览器特性:Web开发者通过一个新的属性passive来告诉浏览器,当前页面内注册的事件监听器内部是否会调用preventDefault函数来阻止事件的默认行为,以便浏览器根据这个信息更好地做出决策来优化页面性能。当属性passive的值为true的时候,代表该监听器内部不会调用preventDefault函数来阻止默认滑动行为,Chrome浏览器称这类型的监听器为被动(passive)监听器。
知道问题就好说了,给addEventListener传入第三个参数

document.addEventListener('touchmove', function (event) {
  event.preventDefault()
}, { passive: false })

大功告成! 突然想到,如果浮层中还需要滚动那就不GG了! so,是不是可以有选择性的禁止滚动(在浮层中元素滚动到最顶部或者最底部之后禁止滚动)。 单独处理浮层中需要滚动的元素;

targetElement.ontouchmove = function (event) {
  const clientY = event.targetTouches[0].clientY - initialClientY

  if (targetElement && targetElement.scrollTop === 0 && clientY > 0) {
    return preventDefault(event)
  }

  if (targetElement && (targetElement.scrollHeight - 1 - targetElement.scrollTop <= targetElement.clientHeight) && clientY < 0) {
    return preventDefault(event)
  }

  event.stopPropagation()
  return true
}

这个方案在ios中完美实现,但是在 android中还是有一点问题;浮层内容拉到最顶部或者最底部的时候依然会带动页面的内容有一定程度的移动。

详解滑动穿透(锁body)终极探索

tua-body-scroll-lock

终极方案来啦!

tua-body-scroll-lock即是在ios、android和PC各个端单独处理,保证在每个端都可以实现完美的效果!

demo

安装

$ npm i -S tua-body-scroll-lock
# OR
$ yarn add tua-body-scroll-lock

使用

移动端

import { lock, unlock } from 'tua-body-scroll-lock'

// 禁止滑动后还需要内部可以滚动的元素(针对移动端ios处理)
const targetElement = document.querySelector("#someElementId");

lock(targetElement)
unlock(targetElement)

PC端

tips: PC端不需要targetElement, 不传targetElement也不想要控制台提示可以传null

import { lock, unlock } from 'tua-body-scroll-lock'

lock()
unlock()

以上所述是小编给大家介绍的滑动穿透(锁body)详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
js获取当前月的第一天和最后一天的小例子
Nov 18 Javascript
点击弹出层效果&amp;弹出窗口后网页背景变暗效果的实现代码
Feb 10 Javascript
JavaScript基础教程之alert弹出提示框实例
Oct 16 Javascript
javascript三元运算符用法实例
Apr 16 Javascript
用js实现放大镜的效果的简单实例
May 23 Javascript
Vue实现双向绑定的方法
Dec 22 Javascript
jQuery中$原理实例分析
Aug 13 jQuery
深入浅出 Vue 系列 -- 数据劫持实现原理
Apr 23 Javascript
JavaScript中callee和caller的区别与用法实例分析
Jun 28 Javascript
Vue Router 实现动态路由和常见问题及解决方法
Mar 06 Javascript
vue pages 多入口项目 + chainWebpack 全局引用缩写说明
Sep 21 Javascript
vant组件中 dialog的确认按钮的回调事件操作
Nov 04 Javascript
一些手写JavaScript常用的函数汇总
Apr 16 #Javascript
浏览器事件循环与vue nextTicket的实现
Apr 16 #Javascript
理理Vue细节(推荐)
Apr 16 #Javascript
ES6知识点整理之Proxy的应用实例详解
Apr 16 #Javascript
js实现删除li标签一行内容
Apr 16 #Javascript
js实现弹出框的拖拽效果实例代码详解
Apr 16 #Javascript
重学 JS:为啥 await 不能用在 forEach 中详解
Apr 15 #Javascript
You might like
解析PHP中的file_get_contents获取远程页面乱码的问题
2013/06/25 PHP
PHP实现的博客欢迎提示功能(很特别哦)
2014/06/05 PHP
ThinkPHP中redirect用法分析
2014/12/05 PHP
PHP内核探索之解释器的执行过程
2015/12/22 PHP
Symfony2使用Doctrine进行数据库查询方法实例总结
2016/03/18 PHP
PHP Mysqli 常用代码集合
2016/11/12 PHP
PHP读取XML格式文件的方法总结
2017/02/27 PHP
laravel 事件/监听器实例代码
2019/04/12 PHP
在html页面上拖放移动标签
2010/01/08 Javascript
浅谈javascript的数据类型检测
2010/07/10 Javascript
jQuery弹出层始终垂直居中相对于屏幕或当前窗口
2013/04/01 Javascript
javascript实现div浮动在网页最顶上并带关闭按钮效果实例
2013/08/13 Javascript
jQuery列表拖动排列具体实现
2013/11/04 Javascript
js倒计时小程序
2013/11/05 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
jQuery元素选择器实例代码
2017/02/06 Javascript
你可能从未使用过的11+个JavaScript特性(小结)
2020/01/08 Javascript
js实现树形数据转成扁平数据的方法示例
2020/02/27 Javascript
jQuery+ajax实现用户登录验证
2020/09/13 jQuery
Vue自定义表单内容检查rules实例
2020/10/30 Javascript
[02:19]DOTA2上海特级锦标赛 观赛指南 Spectator Guide
2016/02/04 DOTA
Sanic框架异常处理与中间件操作实例分析
2018/07/16 Python
Selenium chrome配置代理Python版的方法
2018/11/29 Python
Python格式化字符串f-string概览(小结)
2019/06/18 Python
python实现比较类的两个instance(对象)是否相等的方法分析
2019/06/26 Python
Python MongoDB 插入数据时已存在则不执行,不存在则插入的解决方法
2019/09/24 Python
基于Python爬取爱奇艺资源过程解析
2020/03/02 Python
Python执行时间的几种计算方法
2020/07/31 Python
pycharm 2020 1.1的安装流程
2020/09/29 Python
新加坡第一的杂货零售商:NTUC FairPrice
2020/12/05 全球购物
机械设计及其自动化专业推荐信
2013/10/31 职场文书
行政文员岗位职责
2013/11/08 职场文书
暑期社会实践方案
2014/02/05 职场文书
工作会议主持词
2014/03/17 职场文书
赢在执行观后感
2015/06/16 职场文书
2016年教代会开幕词
2016/03/04 职场文书