这两天做H5页面,使用swiper+iscroll+fastClick,并没有用swiper提供的tap和click事件,自己在元素上bind,因为回调函数是统一处理,就没用swiper的tap,后面发现即使是使用了swiper提供的,也是会有问题,本人用的ios设备,做完一切流畅,但是提交给测试确发现安卓有个问题,如题。
swiper v4.5.0
研究了一下swiper源码,发现初始化的时候会给容器注册一个click事件
这里是用来判断用户当前是否触发touchmove事件,如果是touchmove那么就阻止所有bind元素的click事件,这个逻辑没错啊,于是继续在模拟器中调试。
打了各种断点调试,发现swiper绑定的touchend中代码逻辑执行顺序在两个客户端中是不一样的,神奇。
如上图,ios中先执行了onClick方法,后执行Utils.nextTick的回调;android则相反,先执行nextTick的回调;然后看了下,swiper是怎么封装的回调Utils.nextTick
??? 好像没问题啊,eventLoop执行顺序对的啊。难道是安卓上setTimeout和event执行顺序异于其他浏览器。
敲段代码测试一下(注意,下面这段代码直接用浏览器打开,执行顺序是相同的,但是,找个容器去挂载,比如tomcat,执行顺序的问题就出来了):
<!DOCTYPE html>
<html>
<head>
<title>touchend-click-setTimeout</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport"
content="initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no,target-densitydpi = medium-dpi">
<meta name="format-detection" content="telephone=no">
<meta name="apple-touch-fullscreen" content="YES">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="stylesheet" type="text/css" href="./lib/swiper.css" />
<link rel="stylesheet" type="text/css" href="./lib/pullToRefresh.css" />
<style>
body,html{
padding: 0;
margin: 0;
border: 0;
}
.btn{
height: 50px;
line-height: 50px;
text-align: center;
background: #ccc;
color: #fff;
width: 200px;
margin: 0 auto;
}
</style>
</head>
<body>
<section id="wrapper">
<ul style="background:#F3F4F6;">
<div class="btn">touchend-btn</div>
</ul>
</section>
</body>
<script type="text/javascript" src="./lib/jquery.min.js"></script>
<!-- <script type="text/javascript" src="./lib/fastclick.js"></script>
<script type="text/javascript" src="./lib/iscroll.js"></script>
<script type="text/javascript" src="./lib/pullToRefresh.js"></script>
<script type="text/javascript" src="./lib/swiper.js"></script>
<script type="text/javascript" src="./lib/vconsole.min.js"></script> -->
<script>
// 原生默认的执行顺序:
// ios执行顺序: touchstart -> touchend -> click -> setTimeout
// android执行顺序: touchstart -> touchend -> setTimeout -> click
// FastClick.attach(document.body);
// refresher.init({
// id: "wrapper",
// pullDownAction: function () {
// },
// pullUpAction: function () { }
// });
$('.btn').on('touchstart',function(){
console.log('touchstart');
});
$('.btn').on('touchmove',function(){
console.log('touchmove');
});
$('.btn').on('touchend',function(){
console.log('touchend');
setTimeout(function(){
console.log('touchend:setTimeout');
},0);
});
$('.btn').on('click',function(){
console.log('click');
});
</script>
</html>
结果如下
ios执行顺序: touchstart -> touchend -> click -> setTimeout
android执行顺序: touchstart -> touchend -> setTimeout -> click
到这里我就没继续往下找原因了,直接修改,解决问题。
不知道有没有大佬能帮忙看下,为啥ios和安卓执行顺序会有这种出入?望告知
另附赠一个问题吧,如果你用华为7S的部分机型进行测试,会发现,永远都无法点击自己bind的事件。因为使用了iscroll以后touchmove事件变得极其敏感,所有的click事件触发之前,都会触发touchmove。按照swiper的逻辑,一旦触发touchmove之后,所有的click都被阻止冒泡,就会出现上面说的问题,解决方案如下图:
增加上图这个判定的即可。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。