快速反馈对于任何 UI 的实现都是相当重要的。研究代表,100ms 是界面让用户感到即时的最大延迟。尽管如此,移动网络仍然受到一个巨大的反馈问题的困扰:触摸任何元素后,延迟 300 毫秒。这种延迟是许多用户认为基于 HTML 的 Web 应用程序“卡顿”的最重要缘由之一。在本文中,本文将带你了解移动端点击事件延迟的从诞生到消亡的过程。css
在 2007 年,苹果公司发布首款 iPhone 以前,因为当时的网站广泛为大屏幕设备所设计,为了应对 iPhone 这种小屏幕设备浏览桌面网站的问题,由此,苹果引入了多项变革,其中就包含了“双击缩放准肯定位正文主体,并将其缩放至适合的比例展示”的功能,即双击缩放功能。然而,因为这种双击缩放的操做,在用户第一次单击页面元素时,浏览器并不知道用户是想作双击缩放操做仍是普通的单击操做。所以,IOS Safari 浏览器首先引入了 300 毫秒延迟,用来判断用户是否会再次点击,也就是说,在第一次点击延迟 300 毫秒,300 毫秒后用户没有再次点击则认定为用户在进行普通的单击操做,并触发单击(Click)事件。html
全面的移动开发者与单击事件延迟战争拉开了序幕。鉴于 iPhone 的巨大成功,其余浏览器厂商也都快步跟进纷纷效仿了 iPhone Safari 浏览器的作法。因而,单击事件延迟成为了移动开发者不得不面对的痛。git
虽然从当时来看 300ms 延迟并无什么不妥,然而在愈来愈注重用户体验的移动互联网时代,这种延迟是没法被用户所接受的,加之开发者也能够对网站进行响应式适配,双击缩放的操做变成了一种无关紧要的操做,浏览器厂商开始意识到延迟所带来的体验问题,提出了一些解决方案。github
解决此问题的第一个方法是常识性方法。因为延迟产生的缘由是双击缩放操做,那么就禁用页面缩放功能,最直接的方法就是设置 Viewport 禁止缩放,代码以下:浏览器
<meta name="viewport" content="user-scalable=no"> <!-- 或者 --> <meta name="viewport" content="initial-scale=1,maximum-scale=1">
适用于 Android 的 Chrome 浏览器是第一个引入此更改的应用程序,随后紧接着是 Android 的 Firefox。没有其余浏览器供应商宣布要添加此优化的计划。尽管此解决方案很是巧妙,背后却以牺牲整个页面缩放为代价,带来的影响是对于页面上的图像或小文本,想要进行缩放变得难以完成。即大多数网站都没法从 Android 版 Chrome 和 Android 版 Firefox 的优化中受益。网络
幸运的是,随后 Chrome 团队在 Chrome 32 以后的版本中,提出了新的优秀方案,代码以下:优化
<meta name="viewport" content="width=device-width">
约定当 Viewport 的 width 小于或等于 device-width 时,去除双击缩放功能。这项技术的另外一个关键在于,它仅消除了双击缩放的功能,用户依然可使用双指缩放功能。所以,不存在与禁用缩放相关的可用性和可访问性问题。网站
指针事件是 Microsoft 提出的一系列针对 Web 的新事件,现已成为 W3C 规范。指针事件规范是尝试使用单个事件模型统一咱们对全部输入类型(鼠标,触摸,手写笔等)的处理。根据规范,CSS 属性 touch-action 用于设置触摸屏用户如何操纵元素的区域(例如,浏览器内置的缩放功能)。touch-action 默认值是 auto,当设置为 none 时会禁止用户缩放,能成功解决 300ms 延迟的问题,如:spa
a[href], button { touch-action: none; }
甚至能够添加 touch-action: none 到 body 以彻底禁用双击来缩放(注意:这也将禁用双指缩放功能,所以它与咱们前面讨论的与禁用缩放相关的可访问性和可用性问题相同)。scala
2014年3月13日,W3C 规范增添了新的 touch-action 属性值 manipulation。该属性值提供了一箭双鵰的体验;它容许双指缩放,以免 touch-action: none 出现的可访问性和可用性问题,但它仍然能够经过禁用双击缩放来消除 300ms 的延迟。
FastClick 是一个小型 JavaScript 库,专门旨在防止移动浏览器中的 300ms 点击延迟。FastClick 的实现基础创建于 touchstart ,touchmove 或者 touchend 事件中的任意一个调用 event.preventDefault,mouse 事件 以及 click 事件将不会触发。FastClick 的原理在 touchend 阶段调用 event.preventDefault,而后经过 document.createEvent 建立一个自定义事件 MouseEvents,而后经过 eventTarget.dispatchEvent 触发对应目标元素上绑定的 click 事件。
关于 FastClick 的好处是,它很是容易使用,只需在文档加载后调用 FastClick.attach() 在 body 元素上实例化:
if ('addEventListener' in document) { document.addEventListener('DOMContentLoaded', function() { FastClick.attach(document.body); }, false); }
FastClick足够聪明,能够检测到若是是桌面浏览器或者存在 meta 标记和 touch-action 解决方案的时候,不会执行任何操做。所以,在咱们为全部平台提供真正的解决方案以前,这是一个极好的解决方法。
得益于现代浏览器对 W3C 规范 touch-action: manipulation 的支持性,才真正完全解决了点击事件延迟的问题。touch-action: manipulation 规定浏览器只容许进行滚动和持续缩放操做。任何其它被 touch-action: auto 支持的行为不被支持。启用平移和双指缩放手势,但禁用其余非标准手势,例如双击缩放。 禁用双击缩放功能可减小浏览器在用户点击屏幕时延迟生成点击事件的须要。代码以下:
html { touch-action: manipulation; }
今后,移动端点击事件延迟正式宣告消亡。