Skip to content

Latest commit

 

History

History
914 lines (657 loc) · 42 KB

File metadata and controls

914 lines (657 loc) · 42 KB

八、事件

在本章中,我们将介绍:

  • 使用定向事件
  • 使用滚动事件
  • 使用触摸事件
  • 使用虚拟鼠标事件
  • 使用页面初始化事件
  • 使用页面加载和删除事件
  • 使用页面更改事件
  • 使用页面转换和动画事件
  • 使用布局事件

导言

除了桌面和移动平台的默认本机事件外,jQueryMobile 框架还提供特定事件。它允许您使用 jQuerybind()live()方法绑定到这些事件,从而允许您执行自定义操作。本章向您展示了如何使用 jQueryMobile 框架中可用的事件。

使用定向事件

当移动设备的方向(纵向横向发生变化时,jQueryMobile 框架触发一个orientationchange事件。本食谱向您展示了如何使用orientationchange事件。

准备好了吗

code/08/orientation源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/orientation/main.html启动此代码

怎么做。。。

执行以下步骤:

  1. 创建main.html如下:

    <div id="main" data-role="page" data-theme="e">
      <div data-role="header" data-theme="a">
     <h1>Orientation Events</h1>
      </div>    
      <div data-role="content">
        <p>Change orientation</p>
      </div>
    </div>
  2. <head>部分

    $(window).bind("orientationchange", function(event, data) {
     $("h1").html(data.orientation);
    });

    添加脚本处理orientationchange事件

它是如何工作的。。。

使用页面内容创建main.html,如前面的代码片段所示。添加给定脚本并将orientationchange事件绑定到回调函数。在此,将设备的当前方向设置为页面的h1标题。您可以使用回调函数的data.orientation属性获取设备方向。

加载页面时,更改设备的方向;标题文本将根据当前方向显示纵向横向

还有更多。。。

在不支持方向属性的平台中($.support.orientationfalse),或者$.mobile.orientationChangeEnabled全局配置设置为false时,框架绑定 resize 事件处理程序来处理设备的方向更改。

已启用方向更改的全局配置

您可以在mobileinit事件处理程序中配置配置,该事件处理程序在应用启动时被调用。这必须在包含jquery.mobile.js脚本之前完成。

$(document).bind("mobileinit", function() {
  $.mobile.orientationChangeEnabled = false;
});

使用滚动事件

当您滚动时,jQueryMobile 框架触发 scrollstart 事件。当您停止滚动时,scrollstop事件被触发。此食谱向您展示如何使用这两个事件。

准备好了吗

code/08/scroll源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/scroll/main.html启动此代码

怎么做。。。

执行以下步骤:

  1. 创建main.html页面内容div样式,高度值较大,滚动条出现:

    <div id="main" data-role="page" data-theme="e">
      <div data-role="header" data-theme="a" data-
      position="fixed">
     <h1>Scroll Events</h1>
      </div>    
      <div data-role="content">
        <div style="height: 1000px">Scroll now</div>
      </div>
    </div>
  2. 将以下脚本添加到<head>部分以处理scroll事件:

    $(window).bind("scrollstart", function(event) {
      $("h1").html("Scrolling now...");
    });
    $(window).bind("scrollstop", function(event) {
      $("h1").html("Scrolling done!");
    });

它是如何工作的。。。

创建main.html,如前代码所示。在页面内容中添加一个height1000pxdiv容器。这将使垂直滚动条出现。现在,将给定的脚本添加到页面的<head>部分。将scrollstart事件绑定到更新页眉文本的回调函数。类似地,将scrollstop事件绑定到更新标题文本的回调函数。现在,按住垂直滚动条手柄滚动页面。您可以看到页眉文本显示"Scrolling now...",当您停止或暂停滚动时,文本更新为"Scrolling done!"

还有更多。。。

scrollstart事件如何在 iOS 设备上运行存在一个问题。在滚动期间不允许 DOM 操作,并且一旦滚动停止,事件将排队并触发。因此,在 iOS 设备上处理滚动事件时,请记住这一点。您必须在滚动开始前进行更改,而不是在滚动开始后进行更改。

使用触摸事件

jQueryMobile 框架提供五个触摸事件。它们是tap``taphold``swipe``swipeleftswiperight事件。点击屏幕时触发点击事件。如果点击持续时间较长,则先触发taphold事件,然后在您抬起手指后触发tap事件。当您在屏幕上滑动时,首先触发swipe事件,然后根据滑动动作的方向触发swipeleftswiperight事件。本食谱向您展示了如何使用这些触摸事件。

在此配方中,上次点击屏幕的位置会显示一个黄色框。每次点击并按住时都会创建一个绿色框。您还可以通过在屏幕的左边缘或右边缘滑动蓝色条来查看滑动操作的工作方式。

准备好了吗

code/08/touch源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/touch/main.html启动此代码。

怎么做。。。

要遵循的步骤如下

  1. main.html中,在<head>标签中定义以下样式:

    <style>
      .box { width:60px; height:60px; position:fixed }
      .yellow { background-color:yellow; z-index:1 }
      .green { background-color:green; z-index:2 }
      .blue { background-color: blue; z-index:3; height:100% }
    </style>
  2. 添加带有两个<div>标签的页面内容,标签样式为蓝色条和黄色框:

    <div id="content" data-role="content">
      <div id="movingbox" class="box yellow" style="top:0px; left:0px"></div>
      <div id="edgebar" class="box blue" style="top:0px; left:0px"></div>
    </div>
  3. 将以下脚本添加到<head>部分,以处理taptaphold事件:

    var tapholdflag = false;
    $("#main").live("tap", function(event) {
      var stylestr = "left:" + event.clientX + "px; top:" 
        + event.clientY + "px;"
      if (tapholdflag) {
        var str = "<div class=''box green'' style=''" + 
          stylestr + "''></div>";
        $("#content").append(str).trigger("create");
      } else {
        $("#movingbox").attr("style", 
          stylestr).trigger("refresh");
      }
      tapholdflag = false;
    });
    $("#main").live("taphold", function(event) {
      tapholdflag = true;
    });
  4. 最后,处理的swipeswipeleftswiperight事件:

    $("#main").live("swipe", function(event) {
      $.event.special.swipe.scrollSupressionThreshold = 15;
      $.event.special.swipe.durationThreshold = 1250;
      $.event.special.swipe.horizontalDistanceThreshold = 25;
      $.event.special.swipe.verticalDistanceThreshold = 50;
    });  
    $("#main").live("swipeleft", function(event) {
      $("#edgebar").attr("style", "top:0px; 
        left:0px").trigger("refresh");
    });
    $("#main").live("swiperight", function(event) {
      $("#edgebar").attr("style", "top:0px; 
        right:0px").trigger("refresh"); 
    });

它是如何工作的。。。

main.html中添加style标签,定义boxyellowgreenblue类。添加一个空的带有id="movingbox"div标签,并设置属性class="box yellow"。这将创建一个60px宽的黄色正方形。接下来,添加一个空的带有id="edgebar"div标记,并设置属性class="box blue"。这将创建一个60px``wide blue bar on the edge of the screen as shown in the following screenshot. The yellow box is hidden below the blue bar as it has a lower z-index值。

`How it works...

现在将给定脚本添加到main.html<head>部分。将五个触摸事件中的每一个绑定到回调函数,如图所示。如果抽头持续时间长,则为taphold。因此,定义一个布尔值tapholdflag来跟踪tap事件是否为taphold。在taphold事件处理程序中将其设置为true,并在触发tap事件后将其清除。

tap事件的回调中,首先检查tapholdflag是否已经设置。如果是,那么这是一个taphold事件。创建一个新的绿色框并调用"``create"方法,如图所示。如果tapholdflagfalse,则这是一个简单的点击。更新黄色框的新位置,触发"refresh"方法。最后,清除tapholdflag并将其设置为false

您可以使用event.clientXevent.clientY参数获取分接头位置。将这些值设置为框的lefttop样式属性,以更新其位置。在几个taptaphold事件之后,屏幕看起来类似于以下屏幕截图:

How it works...

现在,将swipe事件绑定到回调函数,并配置swipe事件属性,如代码所示。代码显示了如何配置scrollSupressionThresholddurationThresholdhorizontalDistanceThresholdverticalDistanceThreshold属性。

swipeleft事件绑定到回调,设置蓝条的lefttop样式属性,调用"refresh"方法。这会将条移动到屏幕的左边缘。类似地,将swiperight事件绑定到回调以设置蓝条的righttop样式属性,并调用"refresh"。这会将条移动到屏幕的右边缘。现在,当您向屏幕右侧滑动时,该条移动到右侧边缘,如下面的屏幕截图所示;向左侧轻扫,条形图移回左侧边缘:

How it works...

还有更多。。。

在代码中,swipe事件的回调向您展示了如何配置swipe事件属性。可用配置如下所示:

  • scrollSupressionThreshold10px默认)刷卡距离必须大于此值才能触发事件,否则为scroll事件
  • durationThreshold1000ms默认):如果刷卡持续时间大于此值,则swipe事件被阻止触发
  • horizontalDistanceThreshold30px默认值):水平滑动距离必须大于此值才能触发事件
  • verticalDistanceThreshold75px默认)垂直滑动距离必须小于此值,才能触发事件

tapholdThreshold 属性

当您点击屏幕时,tap事件将触发。如果抽头持续时间超过某个值(默认情况下为750ms,则这将被视为taphold事件。您可以通过如下设置$.event.special.tap.tapholdThreshold属性来配置此持续时间:

$("#main").live("tap", function(event) {
  $.event.special.tap.tapholdThreshold = 1000;
});

默认的tap事件配置适用于大多数平台。因此,只有当你有很强的理由这样做时,才修改它们。

另见

  • 使用虚拟鼠标事件的配方

虚拟鼠标事件

jQueryMobile 框架提供虚拟mousevmouse事件来抽象鼠标和触摸事件。

您不必为每个受支持的平台或设备的触摸和鼠标事件编写单独的处理程序。您只需要为vmouse事件编写事件处理程序,这将在各种平台上工作。框架支持七个vmouse事件:vmousemovevmouseovervmouseoutvmousedownvmouseupvclickvmousecancel。本食谱向您展示了如何使用这些vmouse事件。

准备好了吗

code/08/vmouse源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/vmouse/main.html启动此代码。

怎么做。。。

应遵循的步骤如下:

  1. 为七个vmouse事件创建内容具有七个div标签的main.html,如下所示:

    <div data-role="content">
      <div id="move"></div>
      <div id="over"></div>        
      <div id="out"></div>        
      <div id="down"></div>
      <div id="up"></div>
      <div id="click"></div>
      <div id="cancel"></div>
    </div>
  2. 将以下脚本添加到<head>部分以处理事件vmousemovevmouseovervmouseout事件:

    $("#main").live("pageinit", function(e) {
     $("#main").bind("vmousemove", function(e) {
        $("#move").html("<p>Move: " + e.clientX + ", " 
          + e.clientY + "</p>");
      });
     $("#main").bind("vmouseover", function(e) {
        $("#over").html("<p>Over: " + e.clientX + ", " 
          + e.clientY + "</p>");
      });
     $("#header").bind("vmouseout", function(e) {
        $("#out").html("<p>Out: " + e.clientX + ", " + 
          e.clientY + "</p>");
      });
  3. 接下来,处理的vmousedownvmouseup、和vclick事件:

     $("#main").bind("vmousedown", function(e) {
        var whichbtn;
        switch (e.which) {
          case 1: whichbtn = "Left Button"; break;
          case 2: whichbtn = "Center Button"; break;
          case 3: whichbtn = "Right Button"; break;
          default: whichbtn = "Tap"; break;
        }                        
        $("#down").html("<p>Down: " + e.clientX + ", " 
          + e.clientY + " - " + whichbtn + " </p>");
      });
     $("#main").bind("vmouseup", function(e) {
        $("#up").html("<p>Up: " + e.clientX + ", " + 
          e.clientY + "</p>");
      });
     $("#main").bind("vclick", function(e) {
        $("#click").html("<p>Click: " + e.clientX + ", 
          " + e.clientY + "</p>");
      });
  4. 最后,处理事件vmousecancel如下:

     $("#main").bind("vmousecancel", function(e) {
        $("#cancel").html("<p>Cancel: " + e.clientX + ", 
          " + e.clientY + "</p>");
      });
    });

它是如何工作的。。。

创建main.html、并添加七个空divs以显示七个vmouse事件中每个事件的事件位置。添加给定的脚本并为每个vmouse事件绑定回调函数,如pageinit事件处理程序所示。使用传递给回调函数的事件参数的e.clientXe.clientY值获取vmouse事件的位置。加载页面并移动鼠标执行所述的各种鼠标操作时,屏幕显示如下:

How it works...

移动鼠标时(或在touchmove事件上),触发vmousemove事件。当对事件绑定到的元素执行移动操作时,触发vmouseover事件。当move动作超出事件绑定的元素时,触发vmouseout事件。在前面的代码中,vmouseout事件绑定到h1头。将鼠标移到标题上并移出标题,以查看此参数在屏幕上得到更新。点击鼠标(或点击touchstart事件)时触发vmousedown事件。点击结束时,vmouseup事件跟随down事件(touchend事件)。点击或点击操作时,vclick事件与vmousedownvmouseup事件一起触发。在vmousedown事件处理程序中,您可以使用event.which属性查找单击的鼠标按钮。对于tap事件,此值为0。您可以尝试单击鼠标上的不同按钮,以查看相应的屏幕更新。最后,当鼠标或触摸事件被取消时,vmousecancel事件被触发。

还有更多。。。

框架为vmouse事件提供以下三种配置:

  • $.vmouse.moveDistanceThreshold10px默认):如果移动量大于此值,则为scroll事件。调用vmousecancel事件,取消TouchMove事件。

  • $.vmouse.clickDistanceThreshold10px默认):如果vmouse点击事件已经捕获,则该事件在阻止列表中。然后,所有小于此距离的vmouse点击将被忽略。

  • $.vmouse.resetTimerDuration (1500ms by default): If the interval between vmouse clicks is more than this duration, then it is not a touch event. Scroll, TouchMove, and TouchEnd events use this. The block list is cleared.

    默认的vmouse配置适用于大多数平台。因此,只有当你有很强的理由这样做时,才修改它们。

鼠标坐标

此配方显示使用event.clientXevent.clientY属性获取鼠标坐标。您还可以使用event.pageXevent.pageYscreen.pageXscreen.pageY属性获取屏幕和页面坐标。

在触摸设备上使用 vclick 事件

在触摸式设备上,已知webkit浏览器会在touchend事件触发后大约 300 毫秒后处理点击事件。如果基础对象或背景在此间隙内发生变化,则此延迟可能导致选择不同的目标。另一个问题是,由于时间滞后,将事件与相应的目标相匹配;例如,当使用event.preventDefault()时。为避免触摸设备出现这些问题,请使用click事件而不是vclick事件。

另见

  • 使用触摸事件的配方

页面初始化事件

jQueryMobile 框架提供页面插件,自动处理页面初始化事件。在创建页面之前触发pagebeforecreate事件。pagecreate事件在页面创建之后、小部件初始化之前触发。完成初始化后触发pageinit事件。这个食谱告诉你如何使用这些事件。

准备好了吗

code/08/pageinit源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/pageinit/main.html启动此代码

怎么做。。。

执行以下步骤:

  1. 创建带有三个空的<div>标签的main.html,如下所示:

    <div id="content" data-role="content">
      <div id="div1"></div>
      <div id="div2"></div>
      <div id="div3"></div>
    </div>
  2. 将以下脚本添加到<head>部分以处理pagebeforecreate事件:

    var str = "<a href='#' data-role='button'>Link</a>";
    $("#main").live("pagebeforecreate", function(event) {
      $("#div1").html("<p>DIV1 :</p>"+str);
    });
  3. 接下来,处理pagecreate事件:

    $("#main").live("pagecreate", function(event) {
      $("#div1").find("a").attr("data-icon", "star");
    });
  4. 最后,处理pageinit事件:

    $("#main").live("pageinit", function(event) {
      $("#div2").html("<p>DIV 2 :</p>"+str);
      $("#div3").html("<p>DIV 3 :</p>"+str);
      $("#div3").find("a").buttonMarkup({"icon": "star"});
    });

它是如何工作的。。。

main.html中将三个空divs添加到页面内容中,如图所示。将给定脚本添加到页面。在脚本中,str是一个 HTML 字符串,用于创建具有data-role="button"属性的锚定链接。

添加pagebeforecreate事件的回调,并将str设置为div1容器。由于页面尚未创建,div1中的按钮会自动初始化并增强,如下图所示。

pagecreate事件添加回调。使用 jQueryfind()方法选择div1中的上一个锚按钮,并设置其data-icon属性。由于此更改是在页面初始化之后但在按钮初始化之前进行的,因此会自动为div1按钮显示star图标,如以下屏幕截图所示。最后,添加pageinit事件的回调,并将str添加到div2div3容器中。此时,页面和小部件已经初始化并增强。添加锚定链接现在将仅显示为本机链接,而不会对div2进行任何增强,如以下屏幕截图所示。但是对于div3,找到锚定链接,手动调用按钮插件上的buttonmarkup方法,并将其图标设置为star。现在当您加载页面时,div3中的链接得到如下增强:

How it works...

还有更多。。。

您可以在插件上触发"create""refresh",让 jQueryMobile 框架增强初始化后对页面或小部件所做的动态更改。

页面初始化事件只触发一次

页面初始化事件只触发一次。因此,这是进行任何特定初始化或添加自定义控件的好地方。

不要使用$(document).ready()

$(document).ready()处理程序仅在加载第一个页面或 DOM 第一次准备就绪时工作。如果通过 Ajax 加载页面,则不会触发ready()功能。鉴于,pageinit事件在页面创建、加载和初始化时触发。因此,这是在应用中进行初始化后活动的最佳位置。

$(document).bind("pageinit", callback() {});

页面加载和删除事件

每当外部页面加载到 DOM 中时,jQueryMobile 框架就会触发页面加载事件。加载页面前触发pagebeforeload事件,然后根据页面加载状态触发pageloadpageloadfailed事件。从 DOM 中删除页面时会触发pageremove事件。此配方向您展示了如何使用页面加载和页面删除事件。

准备好了吗

code/08/pageload源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/pageload/main.html启动此代码。

怎么做。。。

执行以下步骤:

  1. 用四个按钮和一个空的div元素创建main.html,如下面的代码片段所示:

    <div id="content" data-role="content">
      <a href="page1.html" data-role="button" data-
        inline="true">Page 1</a>
      <a href="page2.html" data-role="button" data-
        inline="true">Page 2</a>        
      <a href="page3.html" data-role="button" data-
        inline="true">Page 3</a>
      <a href="page4.html" data-role="button" data-
        inline="true">Page 4</a>
      <div id="msgdiv"></div>
    </div>
  2. 将下面的脚本添加到<head>部分,以处理pagebeforeload事件:

    $(document).bind("pagebeforeload", function(event, data) {
      var str = "<p>LOADING PAGE ...</p>"
        + "<p>url: " + data.url + "</p>"
        + "<p>absUrl : " + data.absUrl + "</p>"
        + "<p>dataUrl : " + data.dataUrl + "</p>"
        + "<p>options.type: " + data.options.type + "</p>";
      var re = /page2.html/;
      if ( data.url.search(re) !== -1 ) {
        str += "<p>ABORTED!!! page2.html does not 
          exist.</p>";
        event.preventDefault();
     data.deferred.reject( data.absUrl, data.options);
      }
      re = /page4.html/;
      if ( data.url.search(re) !== -1 ) {
        str += "<p>ABORTED!!! error dialog shown 
          instead.</p>";
        event.preventDefault();
     data.deferred.resolve( data.absUrl, data.options, 
     $("#subpage")); 
      }
      $("#msgdiv").html(str).trigger("refresh");
    });
  3. 接下来,处理pageload事件:

    $(document).bind("pageload", function(event, data) {
      var str = "<p>PAGE LOADED!</p><p>textStatus: " + data.textStatus 
        +   "</p><p>xhr.status : " + data.xhr.status + "</p>";
      $("#msgdiv").append(str).trigger("refresh");
    });
  4. 接下来,用pageloadfailed事件

    $(document).bind("pageloadfailed", function(event, 
     data) {
      var str = "<p>PAGE LOAD FAILED!</p>"+ "<p>textStatus: " + data.textStatus + "</p>"
        + "<p>xhr.status : " + data.xhr.status + "</p>"
        + "<p>errorThrown : " + data.errorThrown + "</p>";
      $("#msgdiv").append(str).trigger("refresh");
    });

    处理任何错误

  5. 同时处理的pageremove事件:

    $("#page1").live("pageremove", function(event) {
      $("#msgdiv").append("<p>PAGE 
        REMOVED!</p>").trigger("refresh");
    });
  6. 现在,创建一个与id="dialog"的对话框,如下所示:

    <div id="dialog" data-role="dialog" data-theme="e" data-add-back-btn="true">
      <div data-role="header">
        <h1>Page Load Failed!</h1>
      </div>
      <div data-role="content">
        <p>There was an error</p>
      </div>      
    </div>
  7. 最后,用按钮创建page1.html返回#main,如下代码片段所示:

    <div id="page1" data-role="page" data-theme="e">
      <div data-role="header">
        <h1>Header of Page 1</h1>
      </div>
      <div data-role="content">
        <a href="#" data-role="button" data-
          rel="back">Go to Main Page</a>
      </div>
    </div>

它是如何工作的。。。

main.html中创建#main页面,添加四个具有data-role="button"data-inline="true"属性的锚链接,创建四个内联按钮。这些链接指向page1.htmlpage2.htmlpage3.htmlpage4.html。同时添加一个带有id="msgdiv"的空div容器以显示消息。接下来,在main.html中添加一个带有id="dialog"的对话框。最后,只创建page1.html,如图所示,带有返回主页的链接。其他三个页面未创建。将页面加载和页面删除事件绑定到脚本中给定的回调函数。这些回调函数有两个可用参数。第一个是event对象,第二个是data对象。

pagebeforeload事件的回调中,从data对象获取urlabsUrl(绝对 URL)、dataUrl(数据 URL)和options.type属性。在msgdiv容器中显示它们。options对象与传入$.mobile.loadPage()调用的对象相同。

pageload事件的回调中,获取指示页面加载成功的xhr.status(jQueryXMLHttpRequest对象)和textStatus属性,并显示在msgdiv容器中。

增加pageloadfailed回调函数显示页面加载错误的data.xhr.statusdata.errorThrown属性。最后,添加pageremove回调函数并显示页面已删除的消息。

现在,当您最初加载应用并点击页面 1按钮打开page1.html时,首先触发pagebeforeload事件,然后在页面完全加载后触发pageload事件。导航回主页面,触发pageremove事件。您可以看到显示的这些消息,如以下屏幕截图所示:

How it works...

接下来,在pagebeforeload事件处理程序中,使用正则表达式搜索检查请求的页面还是data.urlpage2.html(不存在)。如果请求了page2.html,则显示自定义错误消息。也可以通过拨打event.preventDefault()来阻止对此请求采取任何进一步行动。最后必须调用data.deferred.reject()方法以拒绝数据对象中包含的延迟对象引用。现在,当您点击第 2 页按钮时,不会触发pageloadfailed事件,如下图所示,自定义错误消息**被中止!!!page2.html 不存在。**显示:

How it works...

点击第 3 页按钮;现在尝试加载不存在的page3.html,并显示覆盖在当前页面上的错误加载页面默认错误消息,如下图所示。您还可以在此处看到来自pageloadfailed事件处理程序的消息。在这种情况下没有进行自定义事件处理。

How it works...

最后,在pagebeforeload回调函数中添加代码,在data.url对象中搜索page4.html。如果找到字符串,则重定向请求以加载#dialog对话框。此外,如果请求了page4.html,则会显示一条自定义消息。现在,为了防止对pagebeforeevent执行默认操作,请调用event.preventDefault()方法。您还必须调用data.deferred.resolve()方法来解析data对象中包含的延迟对象引用。然后,打开#dialog页面,将其作为参数传递给resolve方法,如代码所示。现在,当您单击第 4 页按钮时,将显示自定义错误对话框弹出窗口。当您关闭对话框时,您的自定义消息被中止!!!改为显示错误对话框。显示,如下图所示。您将注意到,pageloadfailed事件回调函数没有被调用。

How it works...

还有更多。。。

如果您通过调用event.preventDefault()方法来阻止默认页面加载事件,那么您必须在完成后通知框架继续处理其他changePage()请求。可以通过调用传递给事件回调函数的data.deferred对象上的reject()resolve()方法来实现。

另见

  • 使用 loadPage()加载第 9 章方法和实用程序中的配方页面

页面更改事件

每当$.mobile.changePage()方法将页面加载到 DOM 中时,jQueryMobile 框架就会触发页面更改事件。在页面更改之前,先触发pagebeforechange事件。然后,触发pagechange事件(成功时)或pagechangefailed事件(失败时)。此配方向您展示了如何使用页面更改事件。

准备好了吗

code/08/pagechange源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/pagechange/main.html启动此代码。

怎么做。。。

执行以下步骤:

  1. 创建带有两个链接的main.html以打开两个对话框,并在其页面内容中创建一个空的div元素,如下所示:

    <div id="content" data-role="content">
      <a href="#dialog1" data-role="button">Dialog 1</a>
      <a href="#dialog2" data-role="button">Dialog 2</a>        
      <div id="msgdiv"></div>
    </div>
  2. 在处理pagebeforechange事件的<head>部分添加以下脚本:

    $(document).bind("pagebeforechange", function(event, data) {
      var str = "<p>CHANGING PAGE ...</p><p>toPage: ";
      str += (!!data.toPage.attr)? data.toPage.attr("data-
        url") : data.toPage;
      str += "</p>";
      $("#msgdiv").html(str).trigger("refresh");
      $("#dialogdiv").html(str).trigger("refresh");
    });
  3. 接下来,处理pagechange事件:

    $(document).bind("pagechange", function(event, data) {
      var str = "<p>CHANGED PAGE ...</p><p>fromPage: ";
      str += (!!data.options.fromPage && !!data.options.fromPage.attr)? 
      data.options.fromPage.attr("data-url") : "none";
      str += "</p><p>options.transition: " + data.options.transition + "</p>";
      $("#msgdiv").append(str).trigger("refresh");
      $("#dialogdiv").append(str).trigger("refresh");
    });
  4. 接下来,用pagechangefailed事件

    $(document).bind("pagechangefailed", function(event, 
     data) {
      var str = "<p>PAGE CHANGE FAILED ...</p>";
      $("#msgdiv").append(str).trigger("refresh");
    });

    处理任何错误

  5. 最后,创建#dialog1对话框,如下所示。第二个对话框#dialog2未创建。

    <div id="dialog1" data-role="dialog" data-theme="e" 
      data-add-back-btn="true">
      <div data-role="header">
        <h1>Dialog Header</h1>
      </div>
      <div data-role="content">
        <div id="dialogdiv"></div>
      </div>
    </div> 

它是如何工作的。。。

main.html中,将两个带有data-role="button"的锚定链接添加到#main页面的内容中。这些链接指向#dialog1#dialog2对话框。另外,添加一个带有id="msgdiv"的空div容器以显示消息。最后,只向main.html添加一个带有id="dialog1"的对话框。将带有id="dialogdiv"的空div容器添加到此对话框。未创建另一个对话框。将页面更改事件绑定到脚本中给定的回调函数。这些回调函数有两个可用参数。第一个是event对象,第二个是data对象。

pagebeforechange事件的回调中,获取data.toPage(目标页面)属性。这可以是字符串或对象。检查这是否是一个对象(如果它有toPage属性),然后使用data.toPage.data-url字符串。在两个信息div容器中显示toPage信息。

pagechange事件的回调中,获取data.fromPage(源页面)属性。再次检查这是一个对象还是一个字符串,如果它是消息div容器中的一个对象,则显示data.fromPage.data-url字符串。此外,data.options对象具有您可以使用的属性,例如transition

最后,在pagechangefailed事件的回调中,显示一条自定义错误消息。当页面第一次加载时,您可以看到下图。toPage显示文本main;此处没有第页的**:**

How it works...

点击对话框 1按钮,将显示以下对话框。toPage值为对话框 1,页面中的主**。使用的转换显示为弹出,这是对话框的默认转换:**

How it works...

关闭此对话框,#main页面打开,显示与以下屏幕截图类似的消息。toPage,而页面中的对话框 1**。使用的转换再次显示为pop:**

How it works...

最后点击对话框 2按钮;由于#dialog2不存在,在pagechangefailed回调中显示自定义错误消息页面更改失败,如下图所示:

How it works...

还有更多。。。

您可以通过调用pagebeforechange事件处理程序中的event.preventDefault()方法来阻止默认的页面更改操作。您可以使用$.mobile.changePage()方法将导航重定向到此处的另一个页面。

页面更改事件的顺序

触发pagebeforechange事件后,changePage()请求将页面加载到 DOM 中,页面发生转换。此时触发pageshowpagehide事件。最后,pagechange事件仅在此之后触发。

另见

  • 使用 changePage()更改第 9 章方法和实用程序中的页面配方

页面转换和动画事件

在页面导航期间,当前页面向外过渡,新活动页面向内过渡。在受支持的位置使用动画。jQueryMobile 框架在页面导航过程中会触发四个页面转换事件,如下所示:

  • pagebeforehide:此事件在当前页面隐藏前触发
  • pagehide:一旦当前页面被隐藏,就会触发此事件
  • pagebeforeshow:此事件在显示新的活动页面之前触发
  • pageshow:一旦显示激活的页面,就会触发此事件

动画完成后,您还可以访问animationComplete插件执行自定义操作。本食谱向您展示了如何使用页面转换事件以及如何使用animationComplete插件。

准备好了吗

code/08/transition源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/transition/main.html启动此代码。

怎么做。。。

执行以下步骤:

  1. 创建main.html,添加#main页面,添加链接打开#page页面和一个空div容器,如下代码片段所示:

    <div id="main" data-role="page" data-theme="e">
      <div data-role="header">
        <h1>Page Transition and Animation Events</h1>
      </div>
      <div id="content" data-role="content">
        <a href="#page" data-role="button" data-
          transition="slide">Page 1</a>
      <div id="msgdiv"></div>
    </div>
  2. 创建#page页面,如下所示,带有返回#main的按钮和显示消息的空div容器:

    <div id="page" data-role="page" data-theme="e">
      <div data-role="header">
        <h1>Page Header</h1>
      </div>
      <div data-role="content">
        <a href="#" data-rel="back" data-role="button">Go Back</a>
      <div id="pagediv"></div>
    </div>
  3. 将以下脚本添加到<head>部分,以便在单击链接时清除消息div容器:

    $("#main").live("pageinit", function(event) {
      $("a").bind("click", function(event, ui) {
        $("#msgdiv").html("");
        $("#pagediv").html("");
      });
    });
  4. 处理pagebeforeshow事件:

    $(document).bind("pagebeforeshow", function(event, data) {
      var str = "<p>BEFORE PAGE SHOW ...</p><p>Previous 
        Page: ";
      str += (!!data.prevPage.attr)? 
        data.prevPage.attr("data-url") : "none";
      str += "</p>";
      $("#msgdiv").append(str).trigger("refresh");
      $("#pagediv").append(str).trigger("refresh");
    });
  5. 处理pagebeforehide事件:

    $(document).bind("pagebeforehide", function(event, 
     data) {
     $(data.nextPage).animationComplete(anim);
      var str = "<p>BEFORE PAGE HIDE ...</p><p>Current Page: ";
      str += (!!data.nextPage.attr)?
        data.nextPage.attr("data-url") : "none";
      str += "</p>";        
      $("#msgdiv").append(str).trigger("refresh");
      $("#pagediv").append(str).trigger("refresh");
    });
  6. 处理pageshow事件:

    $(document).bind("pageshow", function(event, data) {
      var str = "<p>PAGE SHOW!</p><p>Previous Page: ";
      str += (!!data.prevPage.attr)? 
        data.prevPage.attr("data-url") : "none";
      str += "</p>";
      $("#msgdiv").append(str).trigger("refresh");
      $("#pagediv").append(str).trigger("refresh");
    });
  7. 处理的pagehide事件:

    $(document).bind("pagehide", function(event, data) {
      var str = "<p>PAGE HIDE!</p><p>Current Page: ";
      str += (!!data.nextPage.attr)? 
        data.nextPage.attr("data-url") : "none";
      str += "</p>";        
      $("#msgdiv").append(str).trigger("refresh");
      $("#pagediv").append(str).trigger("refresh");
    });
  8. animationComplete()方法:

    anim = function() {
      $("#msgdiv").append("ANIMATION 
        DONE!!!").trigger("refresh");
      $("#pagediv").append("ANIMATION 
        DONE!!!").trigger("refresh");          
    }

    增加回调函数

它是如何工作的。。。

创建main.html和在#main页面的内容中添加一个带有data-role="button"的锚定链接。此链接打开main.html中的#page页面。创建#page页面,如图所示,带有返回#main的链接。分别在页面中添加空的#msgdiv#pagediv容器,以显示消息。在pageinit事件处理程序中绑定锚定链接的click事件,清除之前显示的所有消息。每当您单击应用中的链接时,就会触发此回调。

现在,将四页转换事件绑定到它们的回调函数,如脚本中所示。这些回调函数有两个可用参数。第一个是event对象,第二个是data对象。

pagebeforeshow事件的回调中,获取data.prevPage(上一页)对象。第一次加载时,此字段可以为空。检查是否可用(如果有prevPage属性)并使用data.prevPage.data-url字符串。在两个信息div容器中显示prevPage信息。在pagehide事件的回调中使用类似的逻辑。

同样,在pagebeforehidepagehide事件的回调中,获取并显示data.toPage(源页面)属性。最后,调用animationComplete插件并定义anim回调函数,如pagebeforehide事件处理程序所示。在anim()函数中编写代码,以显示完成的简单**动画!!!**两个 div 容器中的消息,如图所示。

当页面第一次加载时,您可以看到调用了pagebeforeshowpageshow事件处理程序的下图。此时未定义prevPage

How it works...

点击第 1 页按钮打开#page。您可以看到来自pagebeforehidepagebeforeshow事件处理程序的消息,说明当前页面页面,而上一页面。然后,您可以看到**动画完成!!!**来自animationComplete()回调的消息。此时页面可见,pagehidepageshow事件的消息也可以看到:

How it works...

点击返回按钮。现在,#main显示,消息显示与之前一样。本次当前页面,上一页面为页面

How it works...

还有更多。。。

在第一次加载时,和pageshow事件处理程序显示一个空的data.nextPage对象。要在第一次加载时显示正确的值,这两个事件必须在页面加载时和加载jquery.mobile.js脚本文件之前绑定到mobileinit处理程序中的回调函数,如以下代码段所示:

<script>
 $(document).bind("mobileinit", function() {
    $(document).bind("pagebeforeshow", function(event, data) {
    alert(data.nextPage);
  });
  $(document).bind("pageshow", function(event, data) {
    alert(data.nextPage);
  });
});
</script>
<script src="http://code.jquery.com/mobile/1.1.1/jquery.mobile-1.1.1.min.js"></script>

另见

  • 第 7 章配置中的配置默认转换配方

使用布局事件

组件如列表视图和可折叠块通过用户交互动态调整大小。这可能导致控制重叠或定位问题。为了防止这种情况发生,这些组件触发updatelayout事件,jQueryMobile 框架更新整个文档并确保所有组件的布局正确。本食谱向您展示了如何使用updatelayout事件。

准备好了吗

code/08/layout源文件夹复制此配方的完整代码。您可以使用 URLhttp://localhost:8080/08/layout/main.html启动此代码。

怎么做。。。

执行以下步骤:

  1. 创建带有三个可折叠块和一个<div>容器的main.html,如下面的代码片段所示:

    <div data-role="content">
     <div id="msgdiv">Collapsible Blocks</div>
      <div data-role="collapsible" data-theme="a" data-
        collapsed="false">
        <h3>Tallest Mountain</h3>
        Mt. Everest
      </div>
      <div data-role="collapsible" data-theme="a" data-
        collapsed="false">
        <h3>Longest River</h3>
        R. Nile
      </div>
      <div data-role="collapsible" data-theme="a" data-
        collapsed="false">
        <h3>Largest Ocean</h3>
        Pacific
      </div>
    </div>
  2. 将以下脚本添加到<head>部分,以处理updatelayout事件:

    $("#main").live("pageshow", function(event, ui) {
     $("div").bind("updatelayout", function(event) {
        $("#msgdiv").html("updatelayout on : " + event.target.innerHTML);
      });
    });

它是如何工作的。。。

main.html中,在页面内容中添加一个带有id="msgdiv"div容器。添加三个具有data-collapsed="false"属性的可折叠块。添加给定脚本以将pageshow事件(在页面显示时触发)绑定到事件处理程序。这里,将updatelayout事件绑定到回调函数。在此回调中,使用event.target.innerHTML属性获取调用updatelayout事件的可折叠块的文本。在msgdiv块中显示,如图所示。现在,当您加载页面时,可以看到三个可折叠块已展开。

点击第一个显示为最高山峰的区块。您将看到它崩溃,msgdiv文本被更新,显示updatelayout 在:珠穆朗玛峰上,如以下屏幕截图所示:

How it works...

还有更多。。。

当您添加或操作组件或在页面中切换组件的可见性时,jQuery Mobile framework 会根据大多数场景的需要更新布局并调整位置。您必须在这些元素上触发createrefresh方法。但在某些情况下,当您添加或操作控件或切换其可见性时,框架可能无法正确处理定位。在这种情况下,您可以触发updatelayout事件并通知框架更新所有组件并重新定位它们。您可以使用以下代码执行此操作:

(yourselector).trigger("updatelayout");