昨天对博客首页进行了重新设计,使用原生 Javascript 对文章标题添加 Touch 监听事件时,因为一个疑似 BUG 导致了一系列奇葩的问题。

代码

举例如下这个 HTML:

<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width,initial-scale=1" />
  <style>
    body {
      height: 2000px;
      background: #666;
      padding-top: 100px;
    }
    a {
      /*display: inline-block;*/
      background: #ccc;
    }
    div {
      color: #fdfdfd;
      width: 100%;
    }
  </style>
</head>
<body>
  <h2>
    <a>test touch event</a>
  </h2>
  <div></div>
  <script>
    var link = document.querySelector('a');
    var divE = document.querySelector('div');
    link.addEventListener('touchstart', function(event){
      divE.innerText = 'touchstart \n';
    });
    link.addEventListener('touchmove', function(event){
      divE.innerText += 'touchmove \n';
    });
    /*
    link.addEventListener('touchend', function(event){
      divE.innerText += 'touchend \n';
    });
    */
  </script>
</body>
</html>

Chrome 的迷惑行为

以下描述发生在 Blink 引擎浏览器内,也就是一般使用的 Chrome, Chromium 浏览器及以其为基础进行开发的其它浏览器;其它浏览器如 Safari, FireFox, iOS 上的 Chrome (webkit 引擎)则不会因为以下指出的不同而差异化表现。

  • 当 a 元素是默认的 inline 样式,且页面仅有 touchstart 或者 touchmove 监听事件,这针对 a 元素的两个事件都不会触发;

  • 当继续添加 touchend 监听事件后, touchstart 监听事件开始触发,但 touchmove 事件依旧不触发;

  • 再次添加 pointerdown 监听事件(应该还有其它事件也能帮助触发), touchmove 监听事件触发。

当把 a 元素样式改成 inline-block 或者 block 后,则一切正常。

在线演示在这里:

说明

因为这个问题,翻遍了好多资料,愣是没有答案,最后发现居然是个潜藏的 BUG?

先记录,随后有空继续查下资料。目前翻阅过的内容大致有以下这些:

但是没一个真的有用的,仅是知道了 Chrome 对于 touch 事件默认是消极应对的,即不会触发阻断常规动作的行为,但是并不会导致事件监听不生效;对于 touchmove 事件,第一个应该是同步触发的,可以用于阻断默认的移动,但一般不这么做,且默认情况下不允许这么做,之后的 touchmove 事件则是异步触发的。

如何正确地为 Gentoo 的 Portage 包管理器设置代理 详解 Yubikey 5 NFC 的工作原理(整理)
显示 Disqus 评论(需自备梯子)