如何避免 300ms 的点击延迟

  • head标签新增 meta
  • css,html新增 touch-action ```jsx // html

// css html { touch-action: manipulation; }

  1. [FAQ - Ant Design Mobile](https://mobile.ant.design/zh/guide/faq#%E5%A6%82%E4%BD%95%E9%81%BF%E5%85%8D-300ms-%E7%9A%84%E7%82%B9%E5%87%BB%E5%BB%B6%E8%BF%9F)
  2. <a name="PDLZ8"></a>
  3. ## fastclick
  4. 处理移动端点击,延迟 300ms 问题<br />FastClick FT Labs 专门为解决移动端浏览器 300 毫秒点击延迟问题所开发的一个轻量级的库
  5. 实现原理:
  6. 1. 在检测到 touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件
  7. 2. 并把浏览器在300ms之后的click事件阻止掉
  8. [https://github.com/ftlabs/fastclick/](https://github.com/ftlabs/fastclick/)
  9. ```javascript
  10. <script type='application/javascript' src='/path/to/fastclick.js'></script>
  11. if ('addEventListener' in document) {
  12. document.addEventListener('DOMContentLoaded', function() {
  13. FastClick.attach(document.body);
  14. }, false);
  15. }

es6引入

  1. var FastClick = require('fastclick');
  2. FastClick.attach(document.body, options);

fastclick移动端配置

对index.html进行移动端的配置,fastclick是解决移动端300ms延迟的方案

  1. <script src="/fastclick/1.0.6/fastclick.js"></script>
  2. <script>
  3. if ('addEventListener' in document) {
  4. document.addEventListener('DOMContentLoaded', function() {
  5. FastClick.attach(document.body);
  6. }, false);
  7. }
  8. </script>

react配置 fastclick

  1. import FastClick from 'fastclick';
  2. FastClick.attach(document.body, options);
  3. if (window.FastClick) {
  4. window.FastClick.prototype.focus = targetElement => {
  5. /**
  6. * 兼容处理 iOS7,有一些元素(如date、datetime、month等)在setSelectionRange会出现TypeError
  7. * 因为这些元素并没有 selectionStart和selectionEnd的整型数字属性
  8. * 所以一旦引用就会报错,因此排除这些属性才使用setSelectionRange方法
  9. */
  10. // 兼容移动端 dingding开发
  11. const elementType = ['date', 'time', 'month', 'email'].includes(targetElement.type);
  12. if (window.dd?.ios && targetElement.setSelectionRange && !elementType) {
  13. const { length } = targetElement.value || {};
  14. targetElement.setSelectionRange(length, length);
  15. // 修复bug ios 11.3不弹出键盘,这里加上聚焦代码,让其强制聚焦弹出键盘
  16. targetElement.focus();
  17. } else {
  18. targetElement.focus();
  19. }
  20. };
  21. }

vue fastclick

main.js中引用

  1. import fastclick from 'fastclick'
  2. fastclick.attach(document.body)

不需要使用fastclick的场景

  1. FastClick是不会对PC浏览器添加监听事件
  2. Android版 Chrome 32+浏览器,如果设置viewport meta的值为width=device-width,这种情况下浏览器会马上出发点击事件,不会延迟300毫秒
  3. 所有版本的Android Chrome浏览器,如果设置viewport meta的值有user-scalable=no,浏览器也是会马上出发点击事件
  4. IE11+浏览器设置了css的属性touch-action: manipulation,它会在某些标签(a,button等)禁止双击事件
  5. IE10的为 -ms-touch-action: manipulation

    1. <meta name="viewport" content="width=device-width, initial-scale=1">
  6. 如果页面上有一些特定的元素不需要使用 fastclick来立刻触发点击事件,可以在元素的class上添加needsclick

    1. <a class="needsclick">Ignored by FastClick</a>

antd-mobile组件手势操作无效

请检查项目中是不是引入了 fastclick,如果有的话,尝试移除掉再试一下

fastClick原理

https://www.cnblogs.com/ylweb/p/10549040.html

touchstart 事件穿透

说完移动端点击300ms延迟的问题,还不得不提一下移动端点击穿透的问题
可能有人会想,既然click点击有300ms的延迟,那对于触摸屏,我们直接监听touchstart事件不就好了吗?

使用touchstart去代替click事件有两个不好的地方

  1. touchstart是手指触摸屏幕就触发,有时候用户只是想滑动屏幕,却触发了touchstart事件,这不是我们想要的结果
  2. 使用touchstart事件在某些场景下可能会出现点击穿透的现象

什么是点击穿透

假如页面上有两个元素A和B。B元素在A元素之上。

  • 我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素;
  • 当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件
  • 这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click

而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件

  • 但是此时B元素不见了,所以该事件被派发到了A元素身上。
  • 如果A元素是一个链接,那此时页面就会意外地跳转