首页 > 代码库 > 使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 事件详解

使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 事件详解

在前文《使用 jQuery Mobile 与 HTML5 开发 Web App —— jQuery Mobile 默认配置与事件基础》中,Kayo 对 jQuery Mobile 事件的基础作出了一些说明,建议在阅读本文前首先阅读前文,这里 Kayo 再引用前文的重要内容。

“jQuery Mobile 在基于本地事件上,创建了一系列的自定义事件,大部分事件是基于触摸设备的使用情况开发的,当然这些事件对于桌面环境也会有适当的处理,开发者可以使用 bind() 函数绑定到需要的页面对象中。

值得注意的是,jQuery Mobile 是基于 Ajax 导航的,所以采用 bind() 方法绑定的事件无法作用于 Ajax 产生的网页元素中,因此建议开发者使用动态绑定的方法如 live()、delegate() 将事件动态的绑定到相应的元素中。live()、delegate() 等方法可以把 jQuery Mobile 选择器选择的 DOM 元素,在整个 DOM 范围将其持久化,这就意味着,无论该元素是先前存在还是通过 Ajax 动态加载的,事件都会被绑定,如同 CSS 给元素添加样式一样。这在对 Ajax 有比较大依赖的网站中是必须注意的。”

在了解了 jQuery Mobile 的基本情况后,下面再详细介绍 jQuery Mobile 中各个事件的具体情况。

在 jQuery Mobile 中,可以把 jQuery Mobile 事件分为 7 个部分 —— 触摸事件 (Touch events),虚拟鼠标事件 (Virtual mouse events),页面事件 (Page events),设备方向变化事件 (Orientation change event),滚屏事件 (Scroll events),(Layout events),动画事件 (Animation Events)。其中页面事件可以再分为页面加载事件 (Page load events),页面跳转事件 (Page change events),页面显示/隐藏事件 (Page show/hide events),页面初始化事件 (Page initialization events),页面移除事件 (Page remove events) 五种,由于页面事件较多,并且涉及 jQuery 中较复杂的对象使用,将会另写文章介绍。下面分别对除页面事件以外的其他事件进行详细介绍。

一.触摸事件 (Touch events)

  • tap(轻击) 一次快速完整的轻击后触发
  • taphold(轻击不放)轻击不放并维持 750ms (可以自定义该时间)后触发
  • swipe(划动) 1s (可以自定义该事件) 内水平拖拽大于 30px ,同时垂直方向向拖曳小于 75px 的事件发生时触发
  • swipeleft(左划)划动事件为向左的方向时触发
  • swiperight(右划)划动事件为向右的方向时触发

在上文中,Kayo 介绍过如何改变 jQuery Mobile 的默认配置,其实除了默认配置外,jQuery Mobile 还有其他一些拓展的配置可供大家自定义,其中就包含一些事件配置。

taphold(轻击不放)

默认情况下,taphold 的触发条件是轻击(tap)元素超过 750ms ,这个条件是可以自定义的,方法与自定义默认配置一样。具体的选项如下:

  • $.event.special.tap.tapholdThreshold (默认: 750ms) – 这个值决定了需要轻击 (tap) 元素超过才出时间才会触发 taphold 事件。

swipe(划动)

默认情况下,swipe 的触发条件是在 1s 内水平拖曳大于 30px ,同时垂直方向拖曳小于 75px ,这些也可以自定义,具体的选项如下:

  • $.event.special.swipe.scrollSupressionThreshold (默认: 10px) – 水平拖曳大于这个值时,jQuery Mobile 会抑制页面滚动。
  • $.event.special.swipe.durationThreshold (默认: 1000ms) – 划动时间超过这个值时,这次拖曳不会触发 swipe 事件。
  • $.event.special.swipe.horizontalDistanceThreshold (默认: 30px) – 水平拖曳距离超过这个值时才会触发 swipe 事件。
  • $.event.special.swipe.verticalDistanceThreshold (默认: 75px) – 垂直拖曳距离小于这个值时才会触发 swipe 事件。

注意 jQuery Mobile 中描述宽度、高度、距离使用的单位是 px ,实际使用时默认已经以此为单位,不用再另外填写单位,例如:

$.event.special.swipe.horizontalDistanceThreshold = 100;

从上面的触摸事件中,我们不难发现,jQuery Mobile 与 jQuery 真的有很大区别,之前 Kayo 曾经介绍过,jQuery Mobile 与 jQuery 相比更像一个 UI 库,这都是为了适合快速的移动开发,也可以说,这都是为了快速制作 Web Apps ,加上本文所介绍的各种触摸事件,jQuery Mobile 已经可以由以上的组件开发出完善的 Web Apps 了,并且如果你已经熟悉 jQuery ,那么整个开发过程会是更快速的。

二.虚拟鼠标事件 (Virtual mouse events)

Kayo 在本系列的文章中曾经多次提到,jQuery Mobile 是针对触摸设备设计的,同时对 PC 等桌面环境也有着良好的支持(当然,对于非触摸的移动设备也有完善的处理机制),但是对于触摸设备和桌面环境,鼠标操作有很大的区别 —— 触摸设备使用的是触摸输入代替鼠标输入,因此,jQuery Mobile 创建了一种事件来整合两种环境下的事件差异,也就是接下来要介绍的虚拟鼠标事件。

虚拟鼠标事件会保留桌面环境下鼠标操作的一些特性, 例如:vmouseup 总会在 vmousedown 之前被触发,vmousedown 总会在 vmouseup 之前被触发,可以取得事件对象的 pageX, pageY, screenX, screenY, clientX, clientY 等属性。

  • vmouseover 处理触摸设备下的 touch 或者桌面环境下的 mouseover 的事件
  • vmousedown 处理触摸设备下的 touchstart 或者桌面环境下的 mousedown 的事件
  • vmousemove 处理触摸设备下的 touchmove 或者桌面环境下的 mousemove 的事件
  • vmouseup 处理触摸设备下的 touchend 或者桌面环境下的 mouseup 的事件
  • vclick 处理触摸设备下的 touchend 或者桌面环境下的 click 的事件。在触摸设备上,这个事件会在 vmouseup 事件之后触发的。
  • vmousecancel 处理触摸设备下的 touch 或者 桌面环境下的 mousecancel 的事件

特别注意的是,在使用 vclick 时需要谨慎。因为在触摸设备中使用 vclick 时,Webkit 内核的浏览器会在 touchend 事件触发后生成 mousedown,mouseup 和 click 事件,这些事件的目标对象会在它们被触发时被计算出来,而且是基于 touch 事件的位置计算出来的,因此在某些情况下(不同的设备,或是不同的 OS)可能会导致这个计算结果出现差异,这就意味着实际的点击的目标和最终的目标可能不同。所以,jQuery Mobile 建议开发者在一些容易发生以上情况(如显示/隐藏元素,或是屏幕过场等内容被大量改变的情况)的时候上使用 click 代替 vclick 事件。

三.设备方向变化事件 (Orientation change event)

orientationchange

在 jQuery Mobile 中,最让 Kayo 惊喜的 API 莫过于设备方向变化事件 orientationchange ,这也是 jQuery Mobile 中唯一一个设备方向变化事件,当设备方向变化(即设备在横向和纵向的方向间转变)时,会触发这个事件,并且这个事件的回调函数的事件对象(e 或 event)中会封装一个 orientation 属性,其值为 "portrait" 或 "landscape" ,用来描述设备是改变为纵向时触发事件还是改变为横向时触发事件。

关于 orientationchange 事件绑定的对象,可以是在设备方向变化时出现较大影响的其中一个元素,但考虑到大多数元素都无法准确预测它的变化是否足以触发 orientationchange 事件,Kayo 建议把 orientationchange 事件绑定到 window 对象中,这样的绑定最为稳定有效。例如:

1
2
3
4
$(window).bind( ‘orientationchange‘, function(e){
    if( e.orientation == "portrait" ) alert(‘portrait‘);
    if( e.orientation == "landscape" ) alert(‘landscape‘);
});

注意当设备不支持 orientationchange 事件时,jQuery Mobile 会绑定 resize 代替 orientationchange 事件。 resize 事件是 JavaScript 中的原生事件,在 JavaScript 中当页面窗口改变时会触发该事件。另外,把 $.mobile.orientationChangeEnabled 设置为 false 可以禁止 orientationchange 事件并以 resize 代替。

关于 $.mobile.orientationChangeEnabled ,这里需要扩展说明一下。orientationchange 事件的触发时间与客户端高度、宽度变化的关系在不同的浏览器中可能会不相同,尽管 jQuery Mobile 会从 window.orientation 中获取正确的窗口角度赋予给 event.orientation 处理,但鉴于最终的变化规律在浏览器间有差异,所以如果触发该事件的时间对于客户端高度、宽度变化有很精确的依赖时,开发者可以设置 $.mobile.orientationChangeEnabled = false 禁止触发 orientationchange 事件,并在 resize 的回调函数中判断高度和宽度变化以达到更精确的效果。

四.滚屏事件 (Scroll events)

scrollstart

当页面开始滚动时触发 scrollstart 事件。但由于 IOS 设备会在页面滚动时冻结 DOM 操作,并且把这些操作加入队列,当页面滚动结束时按队列执行这些 DOM 操作,jQuery Mobile 努力寻找让设备在页面滚动开始前执行 DOM 操作,但现阶段考虑到最终得到的 Web Apps 的兼容性,Kayo 不建议利用 scrollstart 的回调函数执行 DOM 操作。

scrollstop

当页面滚动结束时触发 scrollstop 事件。

五.布局事件 (Layout events)

由于页面中的一些组件,如可折叠模块 (collapsible),列表组件搜索 (listview search) 或是 jQuery 显示/隐藏 (show/hide) 等方法,会导致页面内容大小有较大变化,或者页面因此产生滚动条,影响页面布局,这样会对一些依赖页面布局的组件,如固定的顶部工具栏 (fixed headers) 造成干扰。因此,当出现以上情况时,jQuery Mobile 会触发一个事件 updatelayout ,通知其他组件需要调整它们的布局以适应页面变化。为了确保这个过程顺利,也可以手动触发这个事件,例如:

1
2
3
4
5
6
$(function() {
    $(‘#aside‘).hide().trigger(‘updatelayout‘);
    $(document).bind("updatelayout", function(event, ui) {
        // 调整组件
    });
});

六.动画事件 (Animation Events)

animationComplete

jQuery Mobile 提供了 animationComplete 事件,在页面转场等 jQuery Mobile 动画结束时触发。可以利用该事件,配合增加或删除一个 class 来做出自定义的过场效果(为新页面增加一个 class ,添加自定义的 CSS3 动画,使用 pagehide 判断旧页面已隐藏后再使用 animationComplete 判断新页面动画已结束,然后移除 class),例如:

1
2
3
4
5
$(document).bind(‘pagehide‘, function(event, ui) {
    $(ui.nextPage).animationComplete(function() {
        // 移除相应的 class
    });
});

七.事件应用实例

为了让大家更好的理解上面的内容,这里 Kayo 列举一些 jQuery Mobile 事件应用的实例。

修改配置例子

如上面所说,jQuery Mobile 为一些 jQuery Mobile 事件的触发条件提供了灵活的可自定义参数,而自定义的方式与修改 jQuery Mobile 默认配置的方式相同,只是拓展的对象不同而已,如下面的例子:

1
2
3
4
5
$(document).bind(‘mobileinit‘, function(){
    $.event.special.swipe.horizontalDistanceThreshold = 100; // 修改触发 swipe 事件的最小水平拖曳距离为 100(px)
    $.event.special.swipe.verticalDistanceThreshold = 120; // 修改触发 swipe 事件的最大垂直拖曳距离为 120 (px)
    $.mobile.orientationChangeEnabled = false; // 默认禁止触发 orientationChangeEnabled
});

注意不能使用前文中自定义默认配置时利用 jQuery 的 $.extend 扩展 $.event 对象的方法扩展 $.event 对象,只有 $.mobile 可以使用 $.extend 扩展对象。因此事件 API 中只有 $.mobile.orientationChangeEnabled 可以使用 $.extend 方法进行自定义。

触摸事件使用例子

下面的例子会使用 live() 为两个页面的 body 元素分别绑定 swiperight 和 swipeleft 事件,这样在页面上向右划动和向左划动可以在两个页面之间切换。并且本例子会结合“修改配置例子”的调整,把触发 swipe 事件的最小水平拖曳距离和触发 swipe 事件的最大垂直拖曳距离分别修改为 100 和 120 ,读者可以尝试水平划动默认的 30(px) 或垂直方向上滑动超过默认的 75(px) 以检测修改是否有效。

为了达到最好的效果,建议在支持触摸的设备上测试,若使用桌面环境测试,建议在页面空白地方点击鼠标划动。另外由于划动距离已自定义为较大的值,划动时若没有效果不妨加大划动距离。

jQurey Mobile 代码

1
2
3
4
5
6
7
8
9
10
11
12
$(document).bind(‘mobileinit‘, function(){
    $.event.special.swipe.horizontalDistanceThreshold = 100; // 修改触发 swipe 事件的最小水平拖曳距离为 100(px)
    $.event.special.swipe.verticalDistanceThreshold = 120; // 修改触发 swipe 事件的最大垂直拖曳距离为 120 (px)
});
$(function(){
    $("#home").live(‘swipeleft‘, function() {
        $(‘#toPage2‘).click(); // 为首页绑定向左划动事件
    });
    $("#page-2").live(‘swiperight‘, function() {
        $(‘#toHome‘).click(); // 为另一页面绑定向右划动事件
    });
});

主要 HTML 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<div data-role="page" id="home">
 
    <div data-role="header">
        <h1>jQuery Mobile Demo</h1>
    </div>
 
    <div data-role="content">
             
        <p> 本例子中,为两个页面的 body 元素分别绑定了 swipeleft 和 swiperight ,划动后分别触发相应的链接,转到另一个页面,另外使用 data-transition="slide" 把页面过场改为“滑动”效果,从而达到 Apps 中常用的滑动换页效果。</p>
        <a id="toPage2" href="#page-2" data-role="button" data-transition="slide" data-theme="b">向左滑动触发我这个链接</a>
    </div>
 
    <div data-role="footer">
        <h2>Demo By <a href="http://kayosite.com" target="_blank" style="text-decoration: none; ">Kayo</a></h2>
    </div>
</div>
 
<div data-role="page" id="page-2">
 
    <div data-role="header">
        <h1>jQuery Mobile Demo</h1>
    </div>
 
    <div data-role="content">    
        <a id="toHome" href="#home" data-role="button" data-theme="b" data-transition="slide" data-direction="reverse" data-rel="back">向右滑动触发我这个链接</a>  
    </div>
 
    <div data-role="footer">
        <h2>Demo By <a href="http://kayosite.com" target="_blank" style="text-decoration: none; ">Kayo</a></h2>
    </div>
 
</div>