Open libin1991 opened 6 years ago
欢迎关注富途web开发团队 ,缺人从众
有一次给公司做了个自适应的的费用介绍页,主要是关于收费标准的调整,老板表示很重视,适用人群也很多,所以也反馈得到几个不常遇到的问题,其中一个就是关于touchstart与click事件的问题。这里记录一下,欢迎指正。
touchstart
click
某天中午,开发了好几天的费用介绍页终于上线了。运营同学满怀信心地发送了收费标准页面的推广消息,然后我们都潇洒地吃午饭去了。正吃着午饭的时候,收到微信群中某客户的反馈:我们的页面最关键的地方——收费详情点击没有反应!
随后我们查看了前端错误上报和日志,没有任何线索。与客户确认环境,客户使用的是 windows PC 。
但奇怪的是,我测试了多台设备,仍然无法重现问题。在同事的机器上也没能复现这个问题。
我们重新审视了一遍事件绑定的代码,发现其实非常简单。
var tap = 'ontouchstart' in window ? 'touchstart' : 'click'; wrap.addEvenListener(tap, function(){ signUp(); });
唯一有点特殊的就是我们的页面是自适应的,为了避免移动端点击 300ms 延迟,在绑定前做了一下判断,移动端绑定了touchstart事件,PC 端绑定了click事件。然而这段代码看起来也是人畜无害,并不至于导致点击没有反应。
我们再次询问了客户更详细的环境信息,获得了一个非常关键的信息,客户使用的是联想的笔记本。由于在 surface 出来的时候组里有同事关注过,想起来当时联想也出了很多触屏笔记本。于是和客户再次联系,确认了他使用的就是联想的触屏笔记本。
至此问题就非常明确了,问题最终还是定位在绑定的“点击”事件上。我们在检测时只是粗暴地检测了设备是否支持触控事件,却忽略了支持触控事件的仍然可能是 PC 设备,客户仍然可能通过点击鼠标来进行操作。这实际上反映出我们忽略了用户设备的多样性,开发的时候对用户设备做了太多的假设,最终导致我们以为它是一台手机,结果它是一台货真价实的笔记本电脑。
归纳起来,关键的点就是:
至此,问题的原因已经分析完毕,如何应对又成了一个问题。这个问题的关键在于确定不同设备上使用“点击”事件的策略。大致分为如下几种:
function isMobile() { return navigator.userAgent.match(/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i) ? true : false; } var tap = isMobile() ? 'touchstart' : 'click';
//引入FastClick var FastClick = require('tool-fastclick'); //页面初始化时调用 new FastClick(document.body);
注:tool-fastclick是组内 fork 的 FastClick 版本,目前没有开源。我们对其中存在的问题进行了一部分修复,比如:同个页面有多个 select 框选择时,会跳选项的 bug 。
tool-fastclick
其实最好的方案是不要在绑定的时候进行判断,而是对touchstart和click同时绑定,但是在touchstart触发的时候暂时取消后续 click 的响应。
具体的实施方式有三种:
preventDefault()
当然,和上面一样,每种方案都有利弊。
方案1取消了后续click事件的触发,在多个事件绑定叠加或者多人合作的时候,有可能导致一些依赖click事件的逻辑出现bug。
方案2和方案3的原理基本一样,实施起来有一定的复杂度,而且本质上属于 hack 的方案,应对一些非常规场景时就不适用了。比如需要快速连续点击的场景,或者用户点击非常慢的场景等等。
总之,没有万全之策,呵呵……
有人可能会对文章最前提到的收费介绍页比较感兴趣,来了,看这里。
欢迎阅读 原文
有一次给公司做了个自适应的的费用介绍页,主要是关于收费标准的调整,老板表示很重视,适用人群也很多,所以也反馈得到几个不常遇到的问题,其中一个就是关于
touchstart
与click
事件的问题。这里记录一下,欢迎指正。1. 问题
某天中午,开发了好几天的费用介绍页终于上线了。运营同学满怀信心地发送了收费标准页面的推广消息,然后我们都潇洒地吃午饭去了。正吃着午饭的时候,收到微信群中某客户的反馈:我们的页面最关键的地方——收费详情点击没有反应!
随后我们查看了前端错误上报和日志,没有任何线索。与客户确认环境,客户使用的是 windows PC 。
但奇怪的是,我测试了多台设备,仍然无法重现问题。在同事的机器上也没能复现这个问题。
2. 溯源
我们重新审视了一遍事件绑定的代码,发现其实非常简单。
var tap = 'ontouchstart' in window ? 'touchstart' : 'click'; wrap.addEvenListener(tap, function(){ signUp(); });
唯一有点特殊的就是我们的页面是自适应的,为了避免移动端点击 300ms 延迟,在绑定前做了一下判断,移动端绑定了
touchstart
事件,PC 端绑定了click
事件。然而这段代码看起来也是人畜无害,并不至于导致点击没有反应。3. 定位
我们再次询问了客户更详细的环境信息,获得了一个非常关键的信息,客户使用的是联想的笔记本。由于在 surface 出来的时候组里有同事关注过,想起来当时联想也出了很多触屏笔记本。于是和客户再次联系,确认了他使用的就是联想的触屏笔记本。
至此问题就非常明确了,问题最终还是定位在绑定的“点击”事件上。我们在检测时只是粗暴地检测了设备是否支持触控事件,却忽略了支持触控事件的仍然可能是 PC 设备,客户仍然可能通过点击鼠标来进行操作。这实际上反映出我们忽略了用户设备的多样性,开发的时候对用户设备做了太多的假设,最终导致我们以为它是一台手机,结果它是一台货真价实的笔记本电脑。
归纳起来,关键的点就是:
touchstart
和click
事件;touchstart
事件,默认必然会导致触发click
事件,但是触发click
事件,不一定会导致touchstart
事件被触发;touchstart
事件,但是鼠标操作只能触发click
,导致touchstart
不触发;4. 解决办法
至此,问题的原因已经分析完毕,如何应对又成了一个问题。这个问题的关键在于确定不同设备上使用“点击”事件的策略。大致分为如下几种:
1. 均使用click事件
2. 通过UA判断设备是否为移动端,再确认事件类型
function isMobile() { return navigator.userAgent.match(/(blackberry|configuration\/cldc|hp |hp-|htc |htc_|htc-|iemobile|kindle|midp|mmp|motorola|mobile|nokia|opera mini|opera |Googlebot-Mobile|YahooSeeker\/M1A1-R2D2|android|iphone|ipod|mobi|palm|palmos|pocket|portalmmm|ppc;|smartphone|sonyericsson|sqh|spv|symbian|treo|up.browser|up.link|vodafone|windows ce|xda |xda_)/i) ? true : false; } var tap = isMobile() ? 'touchstart' : 'click';
3. 全部使用click,通过FastClick解决300毫秒的延迟问题
//引入FastClick var FastClick = require('tool-fastclick'); //页面初始化时调用 new FastClick(document.body);
4. 万全之策
其实最好的方案是不要在绑定的时候进行判断,而是对
touchstart
和click
同时绑定,但是在touchstart
触发的时候暂时取消后续 click 的响应。具体的实施方式有三种:
touchstart
事件响应中调用preventDefault()
方法,阻止后续click
事件的触发touchstart
事件中设置一些标记,或者取消click
事件的绑定,使得click
事件触发时不会触发我们绑定的逻辑,在一段时间(例如300-500ms)后再恢复当然,和上面一样,每种方案都有利弊。
方案1取消了后续
click
事件的触发,在多个事件绑定叠加或者多人合作的时候,有可能导致一些依赖click
事件的逻辑出现bug。方案2和方案3的原理基本一样,实施起来有一定的复杂度,而且本质上属于 hack 的方案,应对一些非常规场景时就不适用了。比如需要快速连续点击的场景,或者用户点击非常慢的场景等等。
总之,没有万全之策,呵呵……
最后
有人可能会对文章最前提到的收费介绍页比较感兴趣,来了,看这里。