iOS下浏览器document/body的click事件无效的坑

最近要在一个移动端页面上新增一个下拉列表,点击下拉,然后点击页面任何位置列表收回,这个功能很简单,在PC端也实现过很多次,基本思路就是在document/body上绑定click事件,触发时隐藏下拉列表。

开发时一切正常,在Chrome的模拟手机浏览器上测试也一切正常,但是在iOS下的Safari上测试,列表可以展开,在页面任意位置点击收回的功能却失效了。

Chrome模拟手机浏览器上一切正常,真机却有问题,在网上搜索的调试方法基本上都需要Mac(贫穷的我流下了眼泪),只能一点一点修改js来调试了。

首先的思路就是排除其他变量,我在一个测试页面上实现了相同的下拉表单,并在document/body上绑定了click事件,然后发现一切正常。

这就更尴尬了,难道是其他js影响了这里么,认真检查了其它部分,结果发现没有document/body相关的操作(此处消耗了大量的时间,并且是无用功),这个思路也不对,只能面向谷歌/百度编程了,网上的建议如下:

  • 将 click 事件委托到非documentbody的父级元素上。
    这是有效的,如果将body与body内的全部元素之间加一次div,然后将之前绑定到document或者body的事件绑定在此div上,功能就正常了。
  • 给目标元素加一条样式规则 cursor: pointer
    首先无法给document上加样式规则,但是给body加此样式规则的话,功能就正常了,原因是iOS的浏览器下的document和body在加上cursor: pointer这个样式规则后,被认为是可点击元素,也就可以触发click事件了。
    网上说只有a和btn被认为是可点击元素,经过测试,只有document和body是特殊元素,需要加cursor: pointer才可以触发click事件,其他元素均可以正常触发click事件。
  • 绑定touchstart事件。
    这个也是有效的,在移动端touchstart事件总是可以被触发的,所以可以将click事件替换为touchstart事件。如果需要做响应式页面,针对PC端和移动端同时优化的话,比如在jQuery下,可以使用$(document).on('click touchstart', function() {// do something...})

其实问题到这里就解决了(如果就这么解决我也不会写这篇文章了-_-||),但是总有个问题在我心头挥之不去,为什么之前我的测试功能页面只在document绑定click就一切正常,正式页面却不行呢,两个页面明明没什么区别,这个问题不解决怎么能算是学到东西了呢。

对着两个页面苦思冥想了半个小时,突然灵光一闪:页面长度不一样!!!我试着在测试功能页面加了一堆br将页面撑开到超过一屏,然后测试功能页面就出现同样的问题啦。

所以推论如下,iOS下的浏览器,触发document/body的click事件时,如果页面超过一屏,会认为这是网页双击向下翻页的第一次点击,这属于浏览器的默认行为,我们自己定义的click事件就失效了。但是如果页面都没有超过一屏,这个翻页的默认行为不存在,我们自己定义的click事件就可以执行了,大功告成~

猜你喜欢

转载自juejin.im/post/5c5403bff265da2de660dc17