触摸检测:关注“为什么”,而非“如何”

使网站或应用程序“移动友好”的一个常见方面是包含一些调整、附加功能或界面元素,这些元素特别针对触摸屏。开发人员现在经常会问:“如何检测支持触摸的设备?”

触摸功能检测

尽管过去存在一些不兼容性和专有解决方案(例如 Mozilla 的实验性、供应商前缀事件模型),但几乎所有浏览器现在都实现了相同的 触摸事件 模型(基于 Apple 首次为 iOS Safari 引入的解决方案,该解决方案随后被其他浏览器采用,并追溯性地变成了 W3C 草案规范)。

因此,能够以编程方式检测特定浏览器是否支持触摸交互涉及一个非常简单的功能检测。

if ('ontouchstart' in window) {
  /* browser with Touch Events
     running on touch-capable device */
}

此代码片段在现代浏览器中可靠地工作,但旧版本臭名昭著地存在一些怪癖和不一致,需要跳过各种不同的检测策略障碍。如果您的应用程序针对这些旧版浏览器,我建议您查看 Modernizr——特别是其各种 触摸测试方法——它可以解决大多数这些问题。

我上面提到“几乎所有浏览器”都支持此触摸事件模型。这里的主要例外是 Internet Explorer。虽然 IE9 及更早版本不支持任何低级触摸交互,但 IE10 引入了对 Microsoft 自身的 指针事件 的支持。此事件模型(此后已提交给 W3C 标准化)将“指针”设备(鼠标、触笔、触摸等)统一到一个新的事件类别下。由于此模型在设计上不包含任何单独的“触摸”,因此ontouchstart的功能检测自然不起作用。建议检测使用指针事件的浏览器是否在支持触摸的设备上运行的方法是检查navigator.maxTouchPoints的存在及其返回值(请注意,Microsoft 的指针事件目前仍使用供应商前缀,因此在实践中我们将查找navigator.msMaxTouchPoints)。如果该属性存在并返回的值大于0,则表示支持触摸。

if (navigator.msMaxTouchPoints > 0) {
  /* IE with pointer events running
     on touch-capable device */
}

将此添加到我们之前的功能检测中——并且还包括指针事件的非供应商前缀版本以实现未来的兼容性——我们得到一个仍然相当紧凑的代码片段。

if (('ontouchstart' in window) ||
     (navigator.maxTouchPoints > 0) ||
     (navigator.msMaxTouchPoints > 0)) {
      /* browser with either Touch Events of Pointer Events
         running on touch-capable device */
}

触摸检测的用途

现在,已经存在一些常用的“触摸优化”技术,这些技术利用了此类功能检测。检测触摸最常见的用例是提高触摸用户界面的响应速度。

在使用触摸屏界面时,浏览器会在触摸操作(例如点击链接或按钮)与实际点击事件触发时间之间引入人工延迟(大约 300 毫秒)。

更具体地说,在支持触摸事件的浏览器中,延迟发生在touchend和这些浏览器为了与以鼠标为中心的脚本兼容而触发的模拟鼠标事件之间。

touchstart > [touchmove]+ > touchend > <strong>延迟</strong> > mousemove > mousedown > mouseup > click

请参阅 事件监听器测试页面 以查看事件触发的顺序,代码可在 GitHub 上获取

引入此延迟是为了允许用户双击(例如,放大/缩小页面)而不会意外激活任何页面元素。

有趣的是,Android 上的 Firefox 和 Chrome 已为具有固定、不可缩放视口的页面去除了此延迟。

<meta name="viewport" value="... user-scalable = no ...">

请参阅 带有user-scalable=no的事件监听器测试页面代码可在 GitHub 上获取

正在讨论进一步调整 Chrome 在其他情况下的行为——请参阅 Chromium 错误跟踪器中的问题 169642

尽管此辅助功能显然是必要的,但它可能使 Web 应用程序感觉有点滞后且无响应。一个常见的技巧是检查触摸支持,如果存在,则直接对触摸事件(touchstart——用户触摸屏幕时——或touchend——用户抬起手指后)做出反应,而不是传统的click

/* if touch supported, listen to 'touchend', otherwise 'click' */
var clickEvent = ('ontouchstart' in window ? 'touchend' : 'click');
blah.addEventListener(clickEvent, function() { ... });

尽管此类优化现在被广泛使用,但它基于一个逻辑谬误,现在这种谬误正变得越来越明显。

使用指针事件的浏览器中也存在人工延迟。

pointerover > mouseover > pointerdown > mousedown > pointermove > mousemove > pointerup > mouseup > pointerout > mouseout > <strong>延迟</strong> > click

尽管可以扩展上述优化方法来检查navigator.maxTouchPoints,然后将我们的监听器连接到pointerup而不是click,但有一种更简单的方法:将元素的 touch-action CSS 属性 设置为none可以消除延迟。

/* suppress default touch action like double-tap zoom */
a, button {
  -ms-touch-action: none;
      touch-action: none;
}

请参阅 带有touch-action:none的事件监听器测试页面代码可在 GitHub 上获取

错误的假设

需要注意的是,这些基于触摸可用性的优化类型存在一个根本缺陷:它们根据设备功能对用户行为做出假设。更明确地说,上面的示例假设,因为设备能够进行触摸输入,所以用户实际上会将触摸作为与之交互的唯一方式。

几年前,这个假设可能有一定的道理,当时唯一具有触摸输入功能的设备是经典的“移动设备”和“平板电脑”。在这里,触摸屏是唯一可用的输入方法。然而,近几个月来,我们看到了一类全新的设备,它们既具有传统的笔记本电脑/台式电脑外形(包括鼠标、触控板、键盘),具有触摸屏,例如各种 Windows 8 机器Google 的 Chromebook Pixel

顺便说一句,即使在手机或平板电脑的情况下,在某些平台上用户也可以添加其他输入设备。虽然 iOS 仅支持为 iPhone/iPad 配对额外的蓝牙键盘以进行纯文本输入,但 Android 和 Blackberry OS 也允许用户添加鼠标。

在 Android 上,此鼠标将完全像“触摸”一样工作,甚至触发相同的触摸事件和模拟鼠标事件序列,包括两者之间令人讨厌的延迟——因此像我们上面示例中的优化仍然可以正常工作。然而,Blackberry OS 仅触发鼠标事件,从而导致下面概述的相同问题。

此更改的影响正在慢慢地为开发人员所认识:触摸支持不再一定意味着“移动设备”,更重要的是,即使触摸可用,它也可能不是用户选择的首要或唯一输入方法。事实上,用户甚至可能在交互过程中切换任何可用的输入方法。

上面这些简单的代码片段在这一类新设备上可能会产生相当恼人的后果。在使用触摸事件的浏览器中

var clickEvent = ('ontouchstart' in window ? 'touchend' : 'click');

基本上是在说“如果设备支持触摸,则只监听touchend而不监听click”——这在多输入设备上会立即阻止通过鼠标、触控板或键盘进行任何交互。

触摸鼠标?

那么,对于可能也具有其他输入方法的支持触摸的设备,如何解决这个新的难题呢?虽然一些开发人员已开始考虑用额外的用户代理嗅探来补充触摸功能检测,但我认为答案——就像 Web 开发中的许多其他情况一样——是接受我们无法完全检测或控制用户如何与我们的网站和应用程序交互,并且要与输入无关。不要做出假设,我们的代码应该适应所有情况。具体来说,不要将是否对clicktouchend/touchstart做出反应的决策视为互斥的,而应将它们都视为互补的。

当然,这可能涉及更多代码,但最终结果是我们的应用程序将适用于最多的用户。一种方法(对于那些努力使他们以鼠标为中心的界面也适用于键盘用户的开发人员来说已经很熟悉了)是简单地“加倍”您的事件监听器(同时注意通过停止触摸事件后触发的模拟鼠标事件来防止功能触发两次)。

blah.addEventListener('touchend', function(e) {
  /* prevent delay and simulated mouse events */
  e.preventDefault();
  someFunction()
});
blah.addEventListener('click', someFunction);

如果这对于您来说还不够“DRY”,当然还有更花哨的方法,例如只为click定义您的函数,然后通过显式触发该处理程序来绕过令人讨厌的延迟。

blah.addEventListener('touchend', function(e) {
  /* prevent delay and simulated mouse events */
  e.preventDefault();
  /* trigger the actual behavior we bound to the 'click' event */
  e.target.click();
})
blah.addEventListener('click', function() {
  /* actual functionality */
});

不过,最后一个代码片段并没有涵盖所有可能的情况。有关相同原理的更强大的实现,请参阅来自 FT 实验室FastClick 脚本。

与输入无关

当然,与触摸设备上的延迟作斗争并不是开发人员想要检查触摸功能的唯一原因。当前的讨论——例如 Modernizr 中关于 检测鼠标用户 的此问题——现在围绕着为触摸用户提供与鼠标或键盘完全不同的界面,以及特定浏览器/设备是否支持悬停等功能。甚至在 JavaScript 之外,类似的概念(pointerhover媒体功能)也已针对 媒体查询级别 4 提出。但原理仍然相同:由于现在有常见的多种输入设备,因此不再容易(在许多情况下,不可能)确定用户是否在支持触摸的设备上。

Microsoft 指针事件规范中采用的更通用的方法——该方法已安排在 Chrome 等其他浏览器中实施——是朝着正确方向迈出的一步(尽管它仍然需要额外处理键盘用户)。同时,开发人员应注意不要从触摸支持检测中得出错误的结论,并避免无意中锁住越来越多的潜在多输入用户。

更多链接

关于 Patrick H. Lauke

@patrick_h_lauke 自 2001 年初以来一直参与标准和可访问性方面的讨论。直到最近,Patrick 还在 Opera Software 的开发者关系团队担任 Web 布道师。作为一位直言不讳的可访问性和标准倡导者,Patrick 倾向于采用务实的实践方法,而不是纯粹的理论性、高级讨论。

Patrick H. Lauke 的更多文章…

关于 Robert Nyman [荣誉编辑]

技术布道师和 Mozilla Hacks 编辑。发表关于 HTML5、JavaScript 和开放 Web 的演讲和博客文章。Robert 是 HTML5 和开放 Web 的坚定支持者,自 1999 年以来一直在从事 Web 前端开发工作——在瑞典和纽约市。他还定期在 http://robertnyman.com 上发表博客文章,并且喜欢旅行和结识新朋友。

Robert Nyman [荣誉编辑] 的更多文章…


21 条评论

  1. Robert Kaiser

    触摸+鼠标设备并不是“近几个月”才出现的。“近几个月”才出现。带有键盘“底座”的华硕 Transformer 平板电脑已经上市一段时间了。但它们运行的是 Android,正如您提到的,这使得鼠标点击被转换为触摸,显然如此。

    另一方面,触摸屏存在于“传统”台式机上,进一步“模糊”了界限(尽管我当前在 Linux 上的设置中,所有触摸都被转换为鼠标点击并报告为鼠标点击)。

    所有这些发展将走向何方,这将是一个有趣的话题,我们肯定需要越来越多地支持混合触摸/鼠标系统。

    2013 年 4 月 9 日 06:09

  2. Patrick H. Lauke

    Robert,是的,我把那些华硕产品归类到我讨论的“带有附加输入的 Android”中。

    而且您当然是对的,过去台式机上也存在触摸屏……但我认为,它们更多的是例外情况,并不常见。我还记得大约两年前,我花了很多时间试图找到一个漂亮的大触摸屏 LCD,结果只找到少数几个——当时——价格过高的产品。此外,操作系统支持也很糟糕……我相信 Win7 是第一个“正确”支持触摸屏的操作系统,Firefox 和 Chrome 等浏览器——但 IE 除外——甚至在其中支持触摸事件……但同样,当时这更多的是一个边缘案例。

    现在,尤其是在 Win8 系统上,你几乎找不到一台没有触控屏的笔记本电脑/台式机了,现在正是那些只针对触控进行天真优化(以牺牲其他输入方式为代价)的优化方案最容易暴露其弊端的时候。当然,这只是我个人的观点:)

    2013年4月9日 06:26

  3. Andrea

    哦,好吧,作为一名 Web 开发人员,我并不关心用户使用的是什么输入设备。

    我真正想要的是一组能够检测以下事件的事件监听器:单击/触摸、元素拖动、元素放下。

    我并不在乎用户是用手指、鼠标还是激光剑:)

    请浏览器厂商放弃所有那些奇怪的事件,并用某种交互事件来开启新的篇章。

    2013年4月9日 06:34

  4. Patrick H. Lauke

    Andrea,指针事件规范(Pointer Events spec)已经非常接近了,但IndieUI 似乎才是你真正想要的 http://www.w3.org/WAI/intro/indieui……不幸的是,如果我没记错的话,后者在任何浏览器中都没有得到支持……

    2013年4月9日 07:04

  5. Andrea

    是的,当然,IndieUI 确实很棒 :D

    2013年4月9日 07:20

  6. Mary Branscombe

    惠普、华硕、三星等厂商 2 年多前就已经推出了结合触控、手写笔和笔记本功能的机型了;长鼻子又来了。

    2013年4月9日 08:05

  7. Stu Cox

    很棒的文章。

    然而,`'ontouchstart' in window` _从技术上讲_ 仅检测 API 本身;而不是触控屏的存在。它目前对于现代触控设备来说运行得相当可靠**,但这仅仅是因为浏览器在找不到触控屏时会禁用该 API。

    WebKit 非常不愿意这样做;事实上,Chrome 24 发布时该 API 始终处于启用状态,以便他们能够更轻松地与平板电脑和移动版本共享代码,但随后他们意识到这破坏了太多网页,因为这些网页假设此检测意味着“这是一个触控设备”,因此他们不得不实现禁用 API 的这种模式。

    禁用 API 并不是很好,因为它使得难以将“拥有触控屏”视为动态特性……因为它确实可以连接/断开触控屏,但是如果这样做,API 不会在会话期间重新启用。

    也就是说,我不确定 Chrome 是否会撤销此更改。我不完全确定这对整个情况意味着什么。

    ** 在没有触控屏的情况下,它有时会在 Win 8 上的 Chrome 中出现误报;目前尚不清楚原因……

    2013年4月9日 08:30

  8. Patrick H. Lauke

    Stu,你说得对……特性检测只查找 API 本身,并依赖于这样一个事实:至少在 Chrome/WebKit 和 Firefox 中,作为事实上的标准,如果启动浏览器时没有实际存在的触控屏,则不会公开该 API(除了误报,在我的测试中我没有遇到过)。

    的确,这种方法没有考虑到在浏览器运行期间添加/移除触控屏的可能性,也没有解决其他边缘情况,比如多个显示器,其中一个也是触控屏,以及当您将浏览器窗口从一个显示器移动到另一个显示器(或者更糟糕的是,停放在中间)时会发生什么。这就是触控事件 API(iOS)的起源清楚地表明的地方。我怀疑将来会投入多少精力来改变这一点,因为我怀疑指针事件将是未来开发中最受关注的事件,因为它们具有稍微更强大的机制。

    如您所知,人们正在讨论 Modernizr 3 是否能够将特性测试绑定到回调函数,从而实现某种形式的动态查询。如果这里通常查询的 API 是静态的(可能将其绑定到最后发送的事件而不是经典的特性检测,这意味着“先验地”仍然无法确定触控功能、可用性和使用情况),那么看看这种情况如何发展将会“有趣”(请阅读:一场噩梦)。

    但同样,这使得从一开始就根本不尝试控制/依赖这种检测并以输入无关的方式进行设计/开发变得更加重要:)

    2013年4月9日 12:25

  9. Patrick H. Lauke

    Mary……我假设“长鼻子”是指某种隐晦的匹诺曹的隐喻,意味着我在我的抱怨中对事实有所保留?

    的确,我稍微简化了论点。是的,一段时间以来一直存在触控屏/手写笔/平板电脑/平板电脑等类型的设备,但纯粹从主观上来说,我认为与我们现在在 Win 8 设备上看到的强劲推动力相比,它们很少见,因为 8 确实试图推动这种触控/多输入的工作方式。是的,Win 7 甚至更早的版本具有有限的触控功能(尽管我似乎记得直到 Win 7 才支持多点触控,并且在某些情况下,手写笔等的行为类似于鼠标/笔和平板电脑设备,而不是真正识别为真正的触控屏——事实上,IE9 及之前的版本没有内置触控功能)。

    总之,长话短说:对于普通大众来说,我仍然认为只有在 Win 8 上,经济实惠、随时可用的多输入设备(突出显示触控功能)的强劲推动力才开始出现……

    2013年4月9日 12:30

  10. Jake Archibald

    值得注意的是,在大多数浏览器中,“touchend”会在滚动结束时触发,而这很少是你希望触发页面交互的时候。

    在我测试过的浏览器中,只有 Chrome 不会在滚动后触发“touchend”。规范完全含糊不清,所以没有人在这方面犯错。指针事件规范中对此进行了正确的说明。

    2013年4月9日 22:42

  11. Dominykas

    让我看看我是否正确理解了这一点(由于某种原因,我从未以_这种_方式想过)

    * 300 毫秒据说是为了让用户能够双击(或可能执行其他手势)
    * 我们可以通过挂接到触控(并阻止默认操作,以便单击不会触发)来避免它
    * 通过这样做,我们禁用了双击(以及可能的其他任何手势)

    那么,300 毫秒是如何有意义的呢?它解决了什么实际问题?

    与此同时,布道者们却说“不要禁用缩放[使用 user-scalable=no]”……我们无法获胜,是吗?

    2013年4月10日 23:46

  12. Patrick H. Lauke

    “它解决了什么实际问题?”

    它解决了用户希望放大页面,无论他们是否点击了链接/按钮/等的问题。这可能是故意的(“我想放大以更好地阅读链接文本”),也可能仅仅是因为那里碰巧存在一个可激活的元素。无论如何,它允许缩放。

    开发人员痴迷于消除延迟的唯一原因是让他们的 Web 应用感觉“更原生”和更快速。

    “与此同时,布道者们却说“不要禁用缩放[使用 user-scalable=no]”……我们无法获胜,是吗?”

    一如既往,这里没有明确的“胜利”方案。这取决于你的优先级是什么。如果你已经优化了一个 Web 应用(它使用漂亮的超大控件,然后禁用缩放),并且想要消除延迟……这是你的特权。是的,一些低视力用户仍然会对你的大小选择存在问题。如果你确实关心这些用户,请忍受 300 毫秒的延迟(是的,这是明显的,但不是决定性的因素)。

    另一方面,人们正在讨论浏览器是否需要提供一个“始终允许我缩放,无论页面指定了什么”的额外设置(默认情况下关闭)。这也许是两全其美……

    2013年4月12日 04:39

  13. Patrick H. Lauke

    顺便说一句,在我忘记这个小信息之前:根据我在一台带有触控屏的 Windows 8 笔记本电脑上的测试,截至撰写本文时,唯一不支持触控屏(即不触发触控事件也不支持多点触控)的主流浏览器是 Opera 12.x。不过,一旦 Opera 发布其基于 Chromium 的版本,这种情况就会发生变化(使用泄露的预发布版本进行检查)。

    2013年4月14日 05:27

  14. Patrick H. Lauke

    另外:从博客文章中链接到的那个带有 MS 指针事件的预览版 Chromium 构建似乎以略微混乱的顺序触发事件,并不完全符合规范。请参阅我在此处的评论 https://github.com/Modernizr/Modernizr/issues/869#issuecomment-15336713

    2013年4月14日 05:30

  15. Dominykas

    300 毫秒_是_一个主要的障碍。对于客户和用户来说。我见过的任何 UX 建议都是“如果你想让事情感觉即时,请在 50-100 毫秒内提供反馈”。因此,普通 Web 开发人员的选择是两者之一 a) 存在 300 毫秒的主要障碍 b) 禁用缩放——这并不是那么大的障碍,因为很少有人注意到并且更少的人抱怨(大多数人只是带着叹息离开,因为我们已经训练了我们的用户期望 user-scalable=no)

    由于 300 毫秒主要是一个由于没有提供反馈而导致的问题——而不是实际的“浪费时间”……一种解决方案是在 ontouchstart 时提供反馈,而无需取消事件,并在 onclick 时执行实际操作——这对于用户来说可能感觉还可以。为了能够使用它,我们必须能够检测“由于手势而取消的触控”——我们能做到吗?

    请注意,这仍然是额外的工作——并且普通开发人员及其普通客户不喜欢“额外的工作”。

    2013年4月14日 22:38

  16. Patrick H. Lauke

    Dominykas,这种情况并非非此即彼……要么消除延迟并阻止缩放,要么允许缩放并忍受 300 毫秒。

    需要明确的是:用户多年来一直在使用移动设备上的 Web,并且对于普通的网站,他们一直很乐意使用这些网站,尽管存在 300 毫秒的延迟。问题似乎真正出现在开发人员试图制作“类似原生”的 Web 应用时,此时差异变得显而易见。

    无论如何,您可以使用一些技术——包括 fastClick/捕获 touchend 或手术式包含 touch-action:none——只要您不阻止整个页面的双击或手势即可。这使您可以*不*锁定缩放。

    你提出的“由于手势而取消的触控”行不通,因为延迟的全部意义在于等待并观察是否正在发生双击手势……并且查看用户是否将要双击的唯一方法是等待一段时间并监听第二次点击。当然,用户也可以使用捏合/缩放手势而不是双击进行缩放。我还没有测试过,但我怀疑当前的情况将类似于 Jake Archibald 在他的评论中提到的,关于 touchend 即使在所有浏览器(除了 Chrome)中的滚动结束时也会触发,如果你的其中一根手指仍然停留在元素上(一个有趣的边缘情况,我将添加到我的额外测试列表中以进行探索)。如果情况确实如此,则可以通过检查触控点的数量来捕获这些情况——如果仍然存在至少另一个点,或者已更改触控点的集合大于 1,那么 touchend 实际上是多点触控操作的一部分,应该被忽略。想知道指针事件是否也存在同样的弱点——如果是这样,由于指针事件不存在所有触控/已更改触控的数组,这将是一个问题,并且需要单独跟踪任何触控点。

    “这仍然是额外的工作——并且普通开发人员[...]不喜欢‘额外的工作’”

    欢迎来到 Web 开发领域,在这里——为了获得最佳结果——通常可能需要一些额外的工作……我们称之为“成为一名专业人士”;)

    2013年4月15日 00:26

  17. Patrick H. Lauke

    由于我仍在积极处理其博客文章中涉及的一些要点(哈哈),因此还有两个相关的链接

    – 在 Chrome/ium 开发者工具中,如果启用伪造的触控事件,则事件顺序错误/与真实设备不同;如果您不小心或没有意识到此问题,这可能会导致您的测试出错 https://code.google.com/p/chromium/issues/detail?id=181204

    – Windows 8 上的 Firefox 存在一些非常奇怪的问题:目前正在忽略 preventDefault(因此您实际上无法阻止合成鼠标事件和最终的点击触发);mousemove 与 touchmove 一起多次触发(而不是仅在处理触控事件后触发一次);mousedown 也在 touchend 之前触发。 https://bugzilla.mozilla.org/show_bug.cgi?id=861876

    2013年4月15日 08:07

  18. Andrew D. Todd

    你的抱怨太温和了,根本不配被称为抱怨。因此,我建议更进一步。这不能被认为是抱怨——应该被认为是咆哮。

    网站设计存在“皇帝的新装”问题。大量网站设计师设计网站是为了炫耀,并把自己塑造成一个伪职业,对客户的需求毫无兴趣。这导致了与最终用户为敌的网站。

    普通的商人对建筑、室内设计、服装设计等方面都有着本能的、实用的了解。他看到一个店面,就会说:“好,签租约,挂招牌,搬进去!”他不会被自私的建筑师或承包商忽悠,去做一个耗资巨大、时间无限的新的泰姬陵。当然,有一些类型的企业,比如汽车经销商或加油站,以及一些类型的餐厅,确实需要专业的建筑设计,但这些都是例外。同样,大多数男士都穿着他们年轻时习惯穿的衣服。梭罗关于警惕需要新衣服的事业的建议可能适用,衣服可以看作是一整套技能、才能和态度的简写。更重要的是,一个称职的商人不会试图强加一种陌生的着装规范给很大一部分顾客。

    问题是,大多数商人还没有掌握这种关于网页设计的知识。网页设计师能够利用这一点,损害商家的利益以谋求自身的发展。商人永远不知道有多少客户厌恶网站而离开,并且再也不会联系他。

    在我看来,如果浏览器禁用了Java、Javascript和Flash,并且在cookie未禁用时显示某种警告对话框,那么网站就应该能够正常工作。如果你需要cookie,你需要准确地解释你打算如何使用它。我还要补充一点,某些新的HTML 5特性必须能够被关闭,因为它们可能会成为恶意软件的目标。你不能命令你的客户的客户重新配置他的浏览器。这是一种极其傲慢的态度。大海里还有很多其他的鱼。我多次放弃一些企业,因为他们的网站显然很糟糕。你能用文字解释一下——为什么你的新功能重要到足以赶走付费客户?

    网页是一个文档,就像一个文字处理文件。检测输入、放大缩小或任何类似的事情都不是网页的职责。检测输入和所有这些都是浏览器的职责。

    顺便说一句,我还要补充一点,亚马逊可以容忍一些其他企业无法容忍的网站故障,但这主要是因为亚马逊物流系统的效率,它拥有数百个仓库。如果你没有数百个仓库,我建议你模仿亚马逊的优点,而不是缺点。

    2013年4月15日 13:41

  19. brothercake

    我承认,任何人都可以通过测试来应用事件,这让我感到惊讶。

    一些人已经谈到“foo in bar”测试不可靠,因为它们依赖于可能不存在的属性映射假设,我支持这种观点。我已经编写JS超过十年了,这种方法直到最近几年才成为可能,因为旧版本的浏览器根本不会按照你的预期映射这些属性。没有理由让touchstart事件映射到window ontouchstart,这只是DOM0属性映射时代遗留下来的产物,它之所以能起作用,只是因为供应商试图支持人们编写JS的所有这些古怪的方式!

    你不应该测试事件,而应该绑定所有你关心的事件,并使用标志和preventDefault来过滤掉来自同一交互的多个事件。这是编写事件脚本的正确方法;直到最近,它还是编写事件脚本的唯一方法,并且仍然是最健壮的方法。

    2013年4月21日 02:56

  20. J

    blah.addEventListener('touchend', function(e) { /* prevent delay and simulated mouse events */ e.preventDefault(); someFunction() }); blah.addEventListener('click', someFunction());

    这段代码是错误的,因为当添加click事件监听器时,someFunction会立即执行,而不是在click事件触发时执行。

    最后一行应该是blah.addEventListener('click', someFunction);

    2013年4月22日 05:59

  21. Patrick H. Lauke

    哎呀,J发现得很好……我已经修复了那个打字错误/疏忽。

    2013年4月22日 06:57

本文的评论已关闭。