为什么使用jquerymobile的网页,绑定的click事件会被触发两次?

问题描述

在开发一个手机网站的时候,
使用了jquerymobile的js,
以便手机网站支持触摸屏左右拖动的事件处理,
结果上述功能做好了,
却发现原有的click点击事件统统都会被执行两次

详细代码

代码很简单,
示例如下:

<!DocType html>
<html>
<head>
<title>jquerymobile click triggered twice ?</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> 
</head>

<body>
<h1>奇怪了?!!</h1>
<p>Some content here.</p>
<p><img id="test" src="http://www.51roms.com/images/crazy.jpg" alt="Click me"></p>

<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script>
var i = 0;
$(document).bind('pageinit', function() {
    $('#test').bind('click', function(e) {
        alert('clicked: ' + i);
        i ++;
    });
});
</script>
</body>
</html>

补充遇到问题的环境

  1. 系统:windows XP 和 android 2.3
  2. 浏览器:Firefox 最新版,android 2.3自带的chrome
  3. 用html5,引入jquery 1.8和jquerymobile 1.2.0

求助

哪位仁兄有遇到过类似的问题,
且有解决的话,
帮忙告知解决方案,
感激不尽~

阅读 31.3k
5 个回答

首先,我说解决办法,只需要把你所有的script内容放到head里即可

<!DocType html>
<html>
<head>
<title>jquerymobile click triggered twice ?</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1"> 
<script src="http://code.jquery.com/jquery-1.8.2.min.js"></script>
<script src="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.js"></script>
<script>
var i = 0;
$(document).bind('pageinit', function() {
    $('#test').bind('click', function(e) {
        alert('clicked: ' + i);
        i ++;
    });
});
</script>
</head>

<body>
<h1>奇怪了?!!</h1>
<p>Some content here.</p>
<p><img id="test" src="http://www.51roms.com/images/crazy.jpg" alt="Click me"></p>
</body>
</html>

然后,我说说思路,这个问题真的很奇葩,一般人还真不知道为什么会这样。但是我在调试的时候发现,你的js居然加载了两遍!

屏幕快照-2012-11-07-上午12.44.29.png

这就是为什么它会执行两次,因为pageinit被调用了两遍。但是为什么js会加载两次呢?你看看最后的页面结构

屏幕快照-2012-11-07-上午12.46.11.png

跟你书写的完全不一样,多了个<div data-role="page">。因此,答案揭晓了,如果你在页面中没有使用<div data-role="page">,jquery mobile会自己创建一个,因为它必须依赖这个。

它怎么创建呢?把body里面的内容复制一遍塞到div里去,body里有什么东西呢?除了你的img外还有两个script,因此它被塞入到新节点后,浏览器解释为需要加载scirpt里的内容,最后奇迹就发生了。。。

我在本地用你的代码测试了下,也有同样的问题。
然后把jQuery Mobile移除绑定到ready上,就没有这个问题了。
所以应该是jQueryMobile的问题,或者是你使用的方式有问题。
PS:没有用过jQuery Mobile
----
看了下jQuery Mobile的文档,最外层加了个div,设置 data-role="page"就没有问题了

首先感谢三位大牛对我的问题的关注和回答,应该说综合三位的回答就是最完整的答案了:

  • simon兄分析问题很清晰、透彻,一针见血地指出是使用方式的问题;
  • airyland给出了一种巧妙的解决方式,让我思路开阔不少;
  • joyqi的解决方案是非常合适的,专业和敬业让我拜服(凌晨还在帮我分析问题);

总结出现目前遇到的这个问题的原因有两点:

  • 由于赶着做新功能,没有仔细看jQuery Mobile的文档,不了解它init初始化网页会对原有结构做一些调整,需要<div data-role="page"></div>
  • 没有参照jQuery Mobile的示例demo,把jQuery和jQuey Mobile的js引入放到<head></head>里面;

总结最优解决方案有两个

  1. 按joyqi分析的方法,把引入js的代码放到<head></head>里面;
  2. 或者按照simon的方法,把网页内容放到<div data-role="page"></div>容器里面(这种情况js引入代码可以放到它里面,或者也可以放到<head></head>里面);
新手上路,请多包涵

click是浏览器的事件,在移动设备上应该要用移动的事件tap咯

你们说的都有道理,我最后总结了一套方法
1. body最外层加<div data-role="page"></div>
2. 所有的js放在<div data-role="page"></div>

保证OK

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏