共计 2592 个字符,预计需要花费 7 分钟才能阅读完成。
这两天做 H5 页面,使用 swiper+iscroll+fastClick,并没有用 swiper 提供的 tap 和 click 事件,自己在元素上 bind,因为回调函数是统一处理,就没用 swiper,后面发现即使是使用了 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 和安卓执行顺序会有这种出入?望告知