jQuery Mobile:文档准备与页面事件

我正在使用jQuery Mobile,并且我无法理解经典文档就绪和jQuery Mobile页面事件之间的差异。

  • 真正的区别是什么?

    为什么要

    <!-- language: lang-js -->
    
    $(document).ready() {
    
    });
    

    比...更好

    $(document).on('pageinit') {
    
    });
    
  • 当您从一个页面切换到另一个页面时,页面事件的顺序是什么?

  • 如何将数据从一个页面发送到另一个页面,是否可以访问上一页中的数据?


  • jQuery Mobile 1.4更新:

    我原来的文章是针对旧的页面处理方式,基本上是jQuery Mobile 1.4之前的一切。 旧的处理方式现在已被弃用,它将保持活跃,直到(包括)jQuery Mobile 1.5,所以你仍然可以使用下面提到的所有东西,至少到明年和jQuery Mobile 1.6。

    旧事件,包括pageinit不存在了,它们被替换为pagecontainer部件。 Pageinit完全被清除,您可以使用pagecreate来代替,该事件保持不变并且不会被更改。

    如果您对页面事件处理的新方式感兴趣,请在此处查看 ,在任何其他情况下请随时继续阅读本文。 即使你使用jQuery Mobile 1.4 +,你也应该阅读这个答案,它超越了页面事件,所以你可能会发现很多有用的信息。

    较旧的内容:

    这篇文章也可以在我的博客HERE中找到

    $(document).on('pageinit') vs $(document).ready()

    你在jQuery中学习的第一件事就是调用$(document).ready()函数中的代码,以便在DOM加载后立即执行。 但是,在jQuery Mobile中 ,Ajax用于在浏览时将每个页面的内容加载到DOM中。 由于这个$(document).ready()会在加载第一页之前触发,并且在页面刷新后将执行用于页面操作的每个代码。 这可能是一个非常微妙的错误。 在某些系统上它看起来可能正常工作,但在其他系统上可能会导致不稳定,难以重复发生。

    经典的jQuery语法:

    $(document).ready(function() {
    
    });
    

    为了解决这个问题(并相信我这是一个问题), jQuery Mobile开发者创建了页面事件。 简而言之,页面事件是在页面执行的特定点触发的事件。 其中一个页面事件是pageinit事件,我们可以像这样使用它:

    $(document).on('pageinit', function() {
    
    });
    

    我们可以更进一步并使用页面标识而不是文档选择器。 假设我们有一个带有id 索引的 jQuery Mobile页面:

    <div data-role="page" id="index">
        <div data-theme="a" data-role="header">
            <h3>
                First Page
            </h3>
            <a href="#second" class="ui-btn-right">Next</a>
        </div>
    
        <div data-role="content">
            <a href="#" data-role="button" id="test-button">Test button</a>
        </div>
    
        <div data-theme="a" data-role="footer" data-position="fixed">
    
        </div>
    </div>
    

    要执行只能用于索引页的代码,我们可以使用下面的语法:

    $('#index').on('pageinit', function() {
    
    });
    

    Pageinit事件将在每次页面即将被加载并首次显示时执行。 除非手动刷新页面或关闭Ajax页面加载,否则不会再次触发。 如果您希望每次访问页面时执行代码,最好使用pagebeforeshow事件。

    这里有一个工作示例:http://jsfiddle.net/Gajotres/Q3Usv/来演示这个问题。

    关于这个问题还有很多笔记。 无论您是使用1个HTML多页还是多个HTML文件范例,建议将您的所有自定义JavaScript页面处理分隔为一个单独的JavaScript文件。 这会注意到你的代码会更好,但是你会有更好的代码概述,特别是在创建jQuery Mobile应用程序时。

    还有另一个特殊的jQuery Mobile事件,它被称为mobileinit 。 当jQuery Mobile启动时,它触发文档对象上的mobileinit事件。 要覆盖默认设置,请将它们绑定到mobileinitmobileinit使用的一个很好的例子是关闭Ajax页面加载,或者更改默认的Ajax加载器行为。

    $(document).on("mobileinit", function(){
      //apply overrides here
    });
    

    页面事件转换顺序

    首先可以在这里找到所有活动:http://api.jquerymobile.com/category/events/

    假设我们有一个页面A和一个页面B,这是一个卸载/加载顺序:

  • 页面B - 事件pagebeforecreate

  • 页面B - 活动页面创建

  • 页面B - 事件pageinit

  • 页面A - 事件pagebeforehide

  • 页面A - 事件页面删除

  • 第A页 - 活动页面隐藏

  • 第B页 - 活动页面上演

  • 页面B - 活动页面显示

  • 为了更好地理解页面事件,请阅读以下内容

  • pagebeforeloadpageloadpageloadfailed当外部页面加载被解雇
  • pagebeforechangepagechangepagechangefailed是页面更改事件。 当用户在应用程序中的页面之间导航时,会触发这些事件。
  • pagebeforeshowpagebeforehidepageshowpagehide是页面转换事件。 这些事件在转换之前,之中和之后被触发并被命名。
  • pagebeforecreatepagecreatepageinit用于页面初始化。
  • pageremove可以被触发,然后在从DOM中删除页面时进行处理
  • 页面加载jsFiddle示例:http://jsfiddle.net/Gajotres/QGnft/

    如果AJAX未启用,某些事件可能不会触发。

    防止页面转换

    如果出于某种原因需要在某些情况下阻止页面转换,可以使用以下代码完成:

    $(document).on('pagebeforechange', function(e, data){
        var to = data.toPage,
            from = data.options.fromPage;
    
        if (typeof to  === 'string') {
            var u = $.mobile.path.parseUrl(to);
            to = u.hash || '#' + u.pathname.substring(1);
            if (from) from = '#' + from.attr('id');
    
            if (from === '#index' && to === '#second') {
                alert('Can not transition from #index to #second!');
                e.preventDefault();
                e.stopPropagation();
    
                // remove active status on a button, if transition was triggered with a button
                $.mobile.activePage.find('.ui-btn-active').removeClass('ui-btn-active ui-focus ui-btn');;
            }
        }
    });
    

    这个例子在任何情况下都可以工作,因为它会在每次页面转换的时候触发,最重要的是它会在页面转换发生之前阻止页面改变。

    这是一个工作示例:

    防止多个事件绑定/触发

    jQuery Mobile工作方式与传统的Web应用程序不同。 根据您在每次访问某个页面时设法绑定事件的方式,它会反复绑定事件。 这不是一个错误,它只是jQuery Mobile如何处理它的页面。 例如,看看这个代码片段:

    $(document).on('pagebeforeshow','#index' ,function(e,data){
        $(document).on('click', '#test-button',function(e) {
            alert('Button click');
        });
    });
    

    工作jsFiddle例子:http://jsfiddle.net/Gajotres/CCfL4/

    每次访问页面时, #index点击事件将被绑定到button #test-button 。 通过从第1页移动到第2页并回几次来测试它。 有几种方法可以防止此问题:

    解决方案1

    最好的解决方案是使用pageinit来绑定事件。 如果您看一下官方文档,您会发现pageinit只会触发一次,就像文档准备好一样,所以再也无法绑定事件。 这是最好的解决方案,因为您不需要像使用o​​ff方法移除事件一样处理开销。

    工作jsFiddle例子:http://jsfiddle.net/Gajotres/AAFH8/

    这个工作解决方案是基于以前有问题的例子。

    解决方案2

    在绑定之前删除事件:

    $(document).on('pagebeforeshow', '#index', function(){
        $(document).off('click', '#test-button').on('click', '#test-button',function(e) {
            alert('Button click');
        });
    });
    

    工作jsFiddle例子:http://jsfiddle.net/Gajotres/K8YmG/

    解决方案3

    使用jQuery筛选器选择器,如下所示:

    $('#carousel div:Event(!click)').each(function(){
        //If click is not bind to #carousel div do something
    });
    

    因为事件过滤器不是官方jQuery框架的一部分,所以可以在这里找到:http://www.codenothing.com/archives/2009/event-filter/

    简而言之,如果速度是您主要关心的问题,则解决方案2比解决方案1好得多。

    解决方案4

    一个新的,可能是最简单的。

    $(document).on('pagebeforeshow', '#index', function(){
        $(document).on('click', '#test-button',function(e) {
            if(e.handled !== true) // This will prevent event triggering more than once
            {
                alert('Clicked');
                e.handled = true;
            }
        });
    });
    

    工作jsFiddle例子:http://jsfiddle.net/Gajotres/Yerv9/

    Tnx到这个解决方案的sholsinger:http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

    pageChange事件怪癖 - 触发两次

    有时,pagechange事件可能会触发两次,并且与之前提到的问题没有任何关系。

    pagebeforechange事件发生两次的原因是由于changePage中的递归调用,因为toPage不是jQuery增强的DOM对象。 这种递归是危险的,因为开发者被允许在事件中改变toPage。 如果开发人员在pagebeforechange事件处理程序中始终将toPage设置为字符串,则无论该对象是否为对象,都将导致无限递归循环。 页面加载事件将新页面作为数据对象的页面属性传递(应将其添加到文档中,但目前未列出)。 pageload事件因此可以用来访问加载的页面。

    几句话就是这样,因为你通过pageChange发送了额外的参数。

    例:

    <a data-role="button" data-icon="arrow-r" data-iconpos="right" href="#care-plan-view?id=9e273f31-2672-47fd-9baa-6c35f093a800&amp;name=Sat"><h3>Sat</h3></a>
    

    要解决此问题,请使用页面事件转换顺序中列出的任何页面事件。

    页面更改时间

    如前所述,当您从一个jQuery Mobile页面切换到另一个页面时,通常是通过点击指向DOM中已存在的另一个jQuery Mobile页面的链接,或手动调用$ .mobile.changePage,发生多个事件和后续操作。 在高层次上,会发生以下操作:

  • 页面更改过程开始
  • 一个新的页面被加载
  • 该页面的内容是“增强”(样式)
  • 从现有页面转换(滑动/弹出/等)到新页面发生
  • 这是一个平均页面转换基准:

    页面加载和处理: 3毫秒

    页面增强: 45毫秒

    过渡: 604毫秒

    总时间: 670毫秒

    *这些值以毫秒为单位。

    因此,您可以看到转换事件正在执行几乎90%的执行时间。

    数据/参数在页面转换之间进行操作

    在页面转换期间可以从一个页面发送一个参数到另一个页面。 它可以用几种方法完成。

    参考:https://stackoverflow.com/a/13932240/1848600

    解决方案1:

    您可以使用changePage传递值:

    $.mobile.changePage('page2.html', { dataUrl : "page2.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : true, changeHash : true });
    

    并阅读他们这样的:

    $(document).on('pagebeforeshow', "#index", function (event, data) {
        var parameters = $(this).data("url").split("?")[1];;
        parameter = parameters.replace("parameter=","");
        alert(parameter);
    });
    

    例:

    的index.html

    <!DOCTYPE html>
      <html>
        <head>
        <meta charset="utf-8" />
        <meta name="viewport" content="widdiv=device-widdiv, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
        <meta name="apple-mobile-web-app-capable" content="yes" />
        <meta name="apple-mobile-web-app-status-bar-style" content="black" />
        <title>
        </title>
        <link rel="stylesheet" href="http://code.jquery.com/mobile/1.2.0/jquery.mobile-1.2.0.min.css" />
        <script src="http://www.dragan-gaic.info/js/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>
            $(document).on('pagebeforeshow', "#index",function () {
                $(document).on('click', "#changePage",function () {
                    $.mobile.changePage('second.html', { dataUrl : "second.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : false, changeHash : true });
                });
            });
    
            $(document).on('pagebeforeshow', "#second",function () {
                var parameters = $(this).data("url").split("?")[1];;
                parameter = parameters.replace("parameter=","");
                alert(parameter);
            });
        </script>
       </head>
       <body>
        <!-- Home -->
        <div data-role="page" id="index">
            <div data-role="header">
                <h3>
                    First Page
                </h3>
            </div>
            <div data-role="content">
              <a data-role="button" id="changePage">Test</a>
            </div> <!--content-->
        </div><!--page-->
    
      </body>
    </html>

    你们中有些人可能会觉得这很有用。 只需将其粘贴到您的页面上,即可获得在Chrome控制台中触发事件的顺序(Ctrl + Shift + I)。

    $(document).on('pagebeforecreate',function(){console.log('pagebeforecreate');});
    $(document).on('pagecreate',function(){console.log('pagecreate');});
    $(document).on('pageinit',function(){console.log('pageinit');});
    $(document).on('pagebeforehide',function(){console.log('pagebeforehide');});
    $(document).on('pagebeforeshow',function(){console.log('pagebeforeshow');});
    $(document).on('pageremove',function(){console.log('pageremove');});
    $(document).on('pageshow',function(){console.log('pageshow');});
    $(document).on('pagehide',function(){console.log('pagehide');});
    $(window).load(function () {console.log("window loaded");});
    $(window).unload(function () {console.log("window unloaded");});
    $(function () {console.log('document ready');});
    

    您不会在控制台中看到卸载,因为当页面被卸载时(当您离开页面时)会触发它。 像这样使用它:

    $(window).unload(function () { debugger; console.log("window unloaded");});
    

    你会明白我的意思。


    这是正确的方法:

    要执行只能用于索引页的代码,我们可以使用以下语法:

    $(document).on('pageinit', "#index",  function() {
        ...
    });
    
    链接地址: http://www.djcxy.com/p/61929.html

    上一篇: jQuery Mobile: document ready vs. page events

    下一篇: Correct way of using JQuery