簡體   English   中英

jQuery Mobile:准備文檔與頁面事件

[英]jQuery Mobile: document ready vs. page events

我正在使用jQuery Mobile,並且無法理解經典文檔就緒和jQuery Mobile頁面事件之間的區別。

  1. 真正的區別是什么?

    為什么要

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

    勝過

     $(document).on('pageinit') { }); 
  2. 從一頁切換到另一頁時,頁面事件的順序是什么?

  3. 如何將數據從一頁發送到另一頁,並且可以訪問前一頁的數據?

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')$(document).ready()

jQuery中學習的第一件事是調用$(document).ready()函數中的代碼,以便一旦加載DOM,一切都將執行。 但是,在jQuery Mobile中 ,Ajax用於在導航時將每個頁面的內容加載到DOM中。 因此, $(document).ready()將在加載第一頁之前觸發,並且用於頁面操作的每個代碼都將在刷新頁面后執行。 這可能是一個非常微妙的錯誤。 在某些系統上,它似乎工作正常,但在其他系統上,則可能導致不穩定,難以重復的怪異現象發生。

經典jQuery語法:

$(document).ready(function() {

});

為了解決此問題(並相信我這是一個問題), jQuery Mobile開發人員創建了頁面事件。 簡而言之,頁面事件是在頁面執行的特定點觸發的事件。 這些頁面事件之一是pageinit事件,我們可以像這樣使用它:

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

});

我們甚至可以走得更遠,使用頁面ID代替文檔選擇器。 假設我們有一個帶有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事件。 要覆蓋默認設置,請將它們綁定到mobileinit 使用mobileinit的一個很好的例子是關閉Ajax頁面加載,或更改默認的Ajax加載器行為。

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

頁面事件轉換順序

首先,所有事件都可以在這里找到: http : //api.jquerymobile.com/category/events/

假設我們有一個頁面A和一個頁面B,這是一個卸載/加載順序:

  1. 頁面B-事件pagebeforecreate

  2. 頁面B-事件頁面創建

  3. 頁面B-事件pageinit

  4. A頁-事件pagebehidehide

  5. 頁面A-事件頁面刪除

  6. A頁-事件pagehide

  7. 頁面B-事件頁面

  8. 頁面B-活動頁面顯示

為了更好地了解頁面事件,請閱讀以下內容:

  • pagebeforeloadpageloadpageloadfailed當外部加載頁面時被解雇
  • pagebeforechangepagechangepagechangefailed是頁面更改事件。 當用戶在應用程序中的頁面之間導航時,將觸發這些事件。
  • pagebeforeshowpagebeforehidepageshowpagehide是頁面轉換事件。 這些事件在轉換之前,期間和之后都會觸發,並被命名。
  • pagebeforecreatepagecreatepageinit用於頁面初始化。
  • 當從DOM中刪除頁面時,可以觸發pageremove並進行處理

頁面加載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 click事件都將綁定到#test-button按鈕 從第1頁移至第2頁並多次返回進行測試。 有幾種方法可以防止此問題:

解決方案1

最好的解決方案是使用pageinit綁定事件。 如果您查看官方文檔,就會發現pageinit僅會觸發一次,就像准備好文檔一樣,因此不可能再次綁定事件。 這是最好的解決方案,因為您沒有像使用off方法刪除事件時那樣的處理開銷。

可用的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/

對於此解決方案,請向sholsinger發送Tnxhttp : //sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

pageChange事件怪癖-觸發兩次

有時pagechange事件可以觸發兩次,並且與前面提到的問題無關。

pagebeforechange事件發生兩次的原因是由於toPage不是jQuery增強的DOM對象時changePage中的遞歸調用。 這種遞歸很危險,因為允許開發人員在事件內更改toPage。 如果開發人員在pagebeforechange事件處理程序中始終將toPage設置為字符串,則無論它是否是對象,都將導致無限遞歸循環。 pageload事件將新頁面作為數據對象的page屬性傳遞(應將其添加到文檔中,當前未列出)。 因此,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> 

second.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> </head> <body> <!-- Home --> <div data-role="page" id="second"> <div data-role="header"> <h3> Second Page </h3> </div> <div data-role="content"> </div> <!--content--> </div><!--page--> </body> </html> 

解決方案2:

或者,您可以創建一個持久性JavaScript對象以用於存儲。 只要將Ajax用於頁面加載(並且不會以任何方式重新加載頁面),該對象就會保持活動狀態。

var storeObject = {
    firstname : '',
    lastname : ''
}

示例: http//jsfiddle.net/Gajotres/9KKbx/

解決方案3:

您還可以像這樣從上一頁訪問數據:

$(document).on('pagebeforeshow', '#index',function (e, data) {
    alert(data.prevPage.attr('id'));
});

prevPage對象保存完整的上一頁。

解決方案4:

作為最后的解決方案,我們有一個很棒的localStorage HTML實現。 它僅適用於HTML5瀏覽器(包括Android和iOS瀏覽器),但所有存儲的數據都可以通過頁面刷新保持不變。

if(typeof(Storage)!=="undefined") {
    localStorage.firstname="Dragan";
    localStorage.lastname="Gaic";
}

示例: http//jsfiddle.net/Gajotres/J9NTr/

可能是最佳解決方案,但在某些版本的iOS 5.X中將失敗。 這是一個眾所周知的錯誤。

不要使用.live() / .bind() / .delegate()

我忘了提及(和tnx andleer提醒我),不建議使用on / off進行事件綁定/解除綁定,不贊成使用live / die和bind / unbind。

jQuery的.live()方法在1.3版引入API時被視為天賜之物。 在典型的jQuery應用程序中,可能會有許多DOM操作,並且隨着元素的來去去去鈎掛和脫鈎會變得非常繁瑣。 .live()方法可以根據應用程序的選擇器在應用程序的生命期內掛鈎事件。 很好嗎? 錯誤的.live()方法非常慢。 .live()方法實際上將其事件掛接到文檔對象,這意味着該事件必須從生成該事件的元素起泡直到到達文檔。 這可能非常耗時。

現在已棄用。 jQuery團隊的人們不再推薦使用它,我也不推薦使用。即使掛接和取消掛接事件可能很繁瑣,但是如果沒有.live()方法,您的代碼將比使用它快得多。

代替.live()您應該使用.on() .on().live()快大約2-3倍。 看一下該事件綁定基准: http : //jsperf.com/jquery-live-vs-delegate-vs-on/34 ,從那里可以清楚地看到所有內容。

基准測試:

jQuery Mobile頁面事件基准測試有一個出色的腳本。 可以在這里找到: https : //github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js 但是在您執行任何操作之前,我建議您刪除其alert通知系統(每個“更改頁”將通過停止應用程序向您顯示此數據),並將其更改為console.log函數。

基本上,此腳本將記錄您的所有頁面事件,如果您仔細閱讀本文(頁面事件描述),您將知道jQm在頁面增強,頁面轉換...上花費了多少時間。

最后的筆記

始終如此,我的意思是始終閱讀jQuery Mobile官方文檔。 它通常會為您提供所需的信息,並且與某些其他文檔不同,該文檔非常好,帶有足夠的解釋和代碼示例。

變化:

  • 30.01.2013-添加了防止多事件觸發的新方法
  • 2013年1月31日-為頁面轉換之間的數據/參數操作一章添加了更好的說明
  • 2013年3月2日- 在頁面轉換之間的數據/參數操作一章中添加了新的內容/示例
  • 2013年5月22日-添加了用於防止頁面過渡/更改的解決方案,並添加了指向官方頁面事件API文檔的鏈接
  • 2013年5月18日-添加了另一個針對多個事件綁定的解決方案

你們中的有些人可能會發現這很有用。 只需將其復制粘貼到您的頁面上,您將獲得在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() {
    ...
});

jQuery-mobile中的文檔就緒和頁面事件之間的簡單區別是:

  1. 文檔就緒事件用於整個HTML頁面,

     $(document).ready(function(e) { // Your code }); 
  2. 當有頁面事件時,用於處理特定的頁面事件:

     <div data-role="page" id="second"> <div data-role="header"> <h3> Page header </h3> </div> <div data-role="content"> Page content </div> <!--content--> <div data-role="footer"> Page footer </div> <!--footer--> </div><!--page--> 

您還可以使用文檔來處理pageinit事件:

$(document).on('pageinit', "#mypage", function() {

});

使用.on()時,它基本上是您正在使用的實時查詢。

另一方面,.ready(根據您的情況)是靜態查詢。 使用它時,您可以動態更新數據,而不必等待頁面加載。 輸入特定值后,您可以簡單地將值傳遞到數據庫中(如果需要)。

在我們輸入數據(帳戶或帖子甚至評論)的表單中,經常使用實時查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM