IOS下body绑定click事件的bug

今天在做项目的时候,遇到了一个特别莫名奇妙的问题:
我在写动态创建出来的模块点击事件的时候,经常会用到事件代理,把click事件绑定到body上,然后今天忽然发现,这么绑定事件在ios却没有效果,各种浏览器都不行。

为了消除其他代码的影响,我写了一个超级简单的页面,然而结果还是不行

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <title></title>
        <style media="screen">
            html,body{height: 100%;width: 100%;position: relative;background-color: green}
        </style>
    </head>
    <body>
        <div style="position:absolute;height:300px;width:300px;background:red;top:100px;left:100px;">

        </div>
        <script type="text/javascript">
            document.body.addEventListener('click',function(e){
                alert(e.target.tagName);
            })
        </script>
    </body>
</html>

经过测试
1.IOS各版本都存在这个bug,包括ihone、ipad、touch
2.IOS下的各种浏览器无一幸免
3.window,document,body 绑定click事件,都不会被触发

这真是莫名其妙的设定。。。

不过还好,屏蔽掉的只是click,touchstart等其他事件还是可以用的
如果需要把事件代理给body处理的话,click是没办法用了,改用touchstart或者模拟的事件tap吧

另外这里介绍一下tap:

click事件在移动端本身是带有300毫秒的延迟的(有的浏览器貌似要有500ms,其实具体多少也不太好测,通常大家都说300,那就300吧),这个问题会导致click事件在移动端相应很慢,如果大量点击交互的话(比如拼图游戏等),用户体验会特别差,为了解决这个问题,于是诞生了这个tap。

tap其实是一个组合事件:一个touchstart+一个touchend事件,tap事件的设定是延迟很小的,完全避免了click在某些场景下存在的延迟问题。

但是,tap的出现,同时又带来了另外一个问题:击穿!就是当一个浮层上有点击关闭这个浮层的效果时,如果我们使用的tap事件,那就会在点下并抬起的瞬间,这个浮层的display直接设置成none,这时候tap事件虽然进行完了,但是300毫秒之后,还有一个click在那等着,这时候浮层关闭了,这个click事件就会被传递给这个复层下面的内容,下面如果是个链接,那页面就会跳转到这个链接所指向的页面~

为了解决tap带来的新bug,我一般会用下面这种办法(tap执行的时候给body设置pointer-events:none,取消掉所有元素的鼠标及触屏行为,500毫秒之后重新设置pointer-events:all):

//阻止击穿
function preThrough(){
	document.body.throughTimer && clearTimeout(document.body.throughTimer);
	document.body.style.pointerEvents = 'none';
	document.body.throughTimer = setTimeout(function(){
		document.body.style.pointerEvents = 'all';
	},500);
}
IOS下body绑定click事件的bug

发表评论