中高级前端必须注意的40条移动端H5坑位指南( 四 )


* {white-space: pre-line;}复制代码开启硬件加速想动画更流畅吗,开启GPU硬件加速呗!
.elem {transform: translate3d(0, 0, 0);/* transform: translateZ(0); */}复制代码描绘像素边框万年话题,如何描绘一像素边框?
.elem {position: relative;width: 200px;height: 80px;&::after {position: absolute;left: 0;top: 0;border: 1px solid #f66;width: 200%;height: 200%;content: "";transform: scale(.5);transform-origin: left top;}}复制代码控制溢出文本万年话题,如何控制文本做单行溢出和多行溢出?
.elem {width: 400px;line-height: 30px;font-size: 20px;&.sl-ellipsis {overflow: hidden;text-overflow: ellipsis;white-space: nowrap;}&.ml-ellipsis {display: -webkit-box;overflow: hidden;text-overflow: ellipsis;-webkit-line-clamp: 3;-webkit-box-orient: vertical;}}复制代码JS方向禁止点击穿透移动端浏览器里点击操作会存在300ms延迟,往往会造成点击延迟甚至点击无效,这个是众所周知的事情 。
2007年苹果发布首款iphone搭载的Safari为了将桌面端网站能较好地展示在移动端浏览器上而使用了双击缩放 。该方案就是上述300ms延迟的主要原因,当用户执行第一次单击后会预留300ms检测用户是否继续执行单击,若是则执行缩放操作,若否则执行点击操作 。鉴于该方案的成功,其他移动端浏览器也复制了该方案,现在几乎所有移动端浏览器都配备该功能 。而该方案引发的点击延迟被称为点击穿透 。
在前端领域里最早解决点击穿透是jQuery时代的zepto,估计现在大部分同学都未使用过zepto,其实它就是移动端版本的jquery 。zepto封装tap事件能有效地解决点击穿透,通过监听document上的touch事件完成tap事件的模拟,并将tap事件冒泡到document上触发 。
在移动端浏览器上不使用click事件而使用touch事件是因为click事件有着明显的延迟,后续又出现fastclick 。该解决方案监听用户是否做了双击操作,可正常使用click事件,而点击穿透就交给fastclick自动判断 。更多fastclick原理可自行百度,在此不作过多介绍 。
fastclick有现成的NPM包,可直接安装到项目里 。引入fastclick可使用click事件代替tap事件,接入方式极其简单 。
import Fastclick from "fastclick";FastClick.attach(document.body);复制代码禁止滑动穿透移动端浏览器里出现弹窗时,若在屏幕上滑动能触发弹窗底下的内容跟着滚动,这个是众所周知的事情 。
首先明确解决滑动穿透需保持哪些交互行为,那就是除了弹窗内容能点击或滚动,其他内容都不能点击或滚动 。目前很多解决方案都无法做到这一点,全部解决方案都能禁止<body>的滚动行为却引发其他问题 。

  • 弹窗打开后内部内容无法滚动
  • 弹窗关闭后页面滚动位置丢失
  • Webview能上下滑动露出底色
当打开弹窗时给<body>声明position:fixed;left:0;width:100%并动态声明top 。声明position:fixed会导致<body>滚动条消失,此时会发现虽然无滑动穿透,但页面滚动位置早已丢失 。通过scrollingElement获取页面当前滚动条偏移量并将其取负值且赋值给top,那么在视觉上就无任何变化 。当关闭弹窗时移除position:fixed;left:0;width:100%和动态top 。
scrollingElement可兼容地获取scrollTop和scrollHeight等属性,在移动端浏览器里屡试不爽 。
document.scrollingElement.scrollHeight可完美代替曾经的
document.documentElement.scrollHeight ||
document.body.scrollHeight,一眼看上去就是代码减少了 。
该解决方案在视觉上无任何变化,完爆其他解决方案,其实就是一种反向思维和障眼法 。该解决方案完美解决固定弹窗和滚动弹窗对<body>全局滚动的影响,当然也可用于局部滚动容器里,因此很值得推广 。
body.static {position: fixed;left: 0;width: 100%;}复制代码const body = document.body;const openBtn = document.getElementById("open-btn");const closeBtn = document.getElementById("close-btn");openBtn.addEventListener("click", e => {e.stopPropagation();const scrollTop = document.scrollingElement.scrollTop;body.classList.add("static");body.style.top = `-${scrollTop}px`;});closeBtn.addEventListener("click", e => {e.stopPropagation();body.classList.remove("static");body.style.top = "";});复制代码支持往返刷新点击移动端浏览器的前进按钮或后退按钮,有时不会自动执行旧页面的JS代码,这与往返缓存有关 。这种情况在Safari上特别明显,简单概括就是往返页面无法刷新 。
往返缓存指浏览器为了在页面间执行前进后退操作时能拥有更流畅体验的一种策略,以下简称BFCache 。该策略具体表现为:当用户前往新页面前将旧页面的DOM状态保存在BFCache里,当用户返回旧页面前将旧页面的DOM状态从BFCache里取出并加载 。大部分移动端浏览器都会部署BFCache,可大大节省接口请求的时间和带宽 。


推荐阅读