Ich verwende jQuery Mobile und habe Probleme, die Unterschiede zwischen klassischen dokumentbereiten und jQuery Mobile-Seitenereignissen zu verstehen.
Was ist der wahre Unterschied?
Warum sollte
<!-- language: lang-js --> $(document).ready() { });
besser sein als
$(document).on('pageinit') { });
Wie ist die Reihenfolge der Seitenereignisse, wenn Sie von einer Seite zur anderen wechseln?
Wie kann ich Daten von einer Seite zur anderen senden und kann auf Daten von der vorherigen Seite zugegriffen werden?
javascript
jquery
html
jquery-mobile
cordova
user2001897
quelle
quelle
Antworten:
jQuery Mobile 1.4 Update:
Mein ursprünglicher Artikel war für die alte Art der Seitenbearbeitung gedacht, im Grunde alles vor jQuery Mobile 1.4. Die alte Art der Handhabung ist jetzt veraltet und bleibt bis (einschließlich) jQuery Mobile 1.5 aktiv, sodass Sie alle unten genannten Elemente mindestens bis zum nächsten Jahr und jQuery Mobile 1.6 verwenden können.
Alte Ereignisse, einschließlich pageinit , existieren nicht mehr, sie werden durch das Seitencontainer- Widget ersetzt. Pageinit wird vollständig gelöscht und Sie können stattdessen pagecreate verwenden. Dieses Ereignis ist gleich geblieben und wird nicht geändert.
Wenn Sie an einer neuen Art der Behandlung von Seitenereignissen interessiert sind, schauen Sie hier , in jedem anderen Fall können Sie mit diesem Artikel fortfahren. Sie sollten diese Antwort lesen, auch wenn Sie jQuery Mobile 1.4 + verwenden. Sie geht über Seitenereignisse hinaus, sodass Sie wahrscheinlich viele nützliche Informationen finden.
Älterer Inhalt:
Dieser Artikel ist auch als Teil meines Blogs HIER zu finden .
$(document).on('pageinit')
vs.$(document).ready()
Das erste, was Sie in jQuery lernen, ist das Aufrufen von Code innerhalb der
$(document).ready()
Funktion, damit alles ausgeführt wird, sobald das DOM geladen wird. In jQuery Mobile wird Ajax jedoch verwendet, um den Inhalt jeder Seite während der Navigation in das DOM zu laden. Aus diesem Grund$(document).ready()
wird ausgelöst, bevor Ihre erste Seite geladen wird, und jeder Code, der für die Seitenmanipulation vorgesehen ist, wird nach einer Seitenaktualisierung ausgeführt. Dies kann ein sehr subtiler Fehler sein. Auf einigen Systemen scheint es, dass es gut funktioniert, auf anderen kann es jedoch zu unregelmäßigen, schwer zu wiederholenden Verrücktheiten kommen.Klassische jQuery-Syntax:
Um dieses Problem zu lösen (und mir zu vertrauen, dass dies ein Problem ist), haben jQuery Mobile- Entwickler Seitenereignisse erstellt. Kurz gesagt, Seitenereignisse sind Ereignisse, die an einem bestimmten Punkt der Seitenausführung ausgelöst werden. Eines dieser Seitenereignisse ist ein Pageinit- Ereignis, und wir können es folgendermaßen verwenden:
Wir können noch weiter gehen und eine Seiten-ID anstelle der Dokumentauswahl verwenden. Angenommen, wir haben eine jQuery Mobile-Seite mit einem ID- Index :
Um Code auszuführen, der nur für die Indexseite verfügbar ist, können wir diese Syntax verwenden:
Das Pageinit- Ereignis wird jedes Mal ausgeführt, wenn eine Seite geladen und zum ersten Mal angezeigt wird. Es wird erst wieder ausgelöst, wenn die Seite manuell aktualisiert oder das Laden der Ajax-Seite deaktiviert wurde. Wenn Sie möchten, dass Code bei jedem Besuch einer Seite ausgeführt wird, ist es besser, das Ereignis pagebeforeshow zu verwenden .
Hier ist ein funktionierendes Beispiel: http://jsfiddle.net/Gajotres/Q3Usv/ , um dieses Problem zu demonstrieren.
Einige weitere Anmerkungen zu dieser Frage. Unabhängig davon, ob Sie 1 HTML-Paradigma für mehrere Seiten oder mehrere HTML-Dateien verwenden, wird empfohlen, die gesamte benutzerdefinierte Behandlung von JavaScript-Seiten in eine einzige separate JavaScript-Datei zu unterteilen. Dadurch wird Ihr Code besser, aber Sie haben eine viel bessere Codeübersicht, insbesondere beim Erstellen einer jQuery Mobile- Anwendung.
Es gibt auch ein weiteres spezielles jQuery Mobile- Ereignis, das mobileinit heißt . Wenn jQuery Mobile gestartet wird , wird ein mobileinit- Ereignis für das Dokumentobjekt ausgelöst . Um Standardeinstellungen zu überschreiben, binden Sie sie an mobileinit . Eines der guten Beispiele für die Verwendung von mobileinit ist das Deaktivieren des Ladens von Ajax-Seiten oder das Ändern des Standardverhaltens von Ajax Loader.
Übergangsreihenfolge für Seitenereignisse
Zunächst finden Sie alle Veranstaltungen hier: http://api.jquerymobile.com/category/events/
Nehmen wir an, wir haben eine Seite A und eine Seite B, dies ist eine Entlade- / Ladereihenfolge:
Seite B - Ereignisseite vor dem Erstellen
Seite B - Ereignisseite erstellen
Seite B - Ereignis Pageinit
Seite A - Ereignisseite vor dem Ausblenden
Seite A - Ereignis- Pageremove
Seite A - Ereignis pagehide
Seite B - Ereignisseite vor der Show
Seite B - Ereignis pageshow
Zum besseren Verständnis von Seitenereignissen lesen Sie Folgendes:
pagebeforeload
,pageload
Undpageloadfailed
werden ausgelöst , wenn eine externe Seite geladen wirdpagebeforechange
,pagechange
Undpagechangefailed
sind Seite Änderungsereignisse. Diese Ereignisse werden ausgelöst, wenn ein Benutzer zwischen Seiten in den Anwendungen navigiert.pagebeforeshow
,pagebeforehide
,pageshow
Undpagehide
sind Seite Übergangsereignisse. Diese Ereignisse werden vor, während und nach einem Übergang ausgelöst und benannt.pagebeforecreate
,pagecreate
Undpageinit
sind für Seite Initialisierung.pageremove
kann ausgelöst und dann verarbeitet werden, wenn eine Seite aus dem DOM entfernt wirdBeispiel zum Laden einer Seite jsFiddle: http://jsfiddle.net/Gajotres/QGnft/
Seitenübergang verhindern
Wenn aus irgendeinem Grund der Seitenübergang unter bestimmten Bedingungen verhindert werden muss, kann dies mit folgendem Code erfolgen:
Dieses Beispiel funktioniert in jedem Fall, da es bei jedem Seitenübergang ausgelöst wird und, was am wichtigsten ist, einen Seitenwechsel verhindert, bevor ein Seitenübergang stattfinden kann.
Hier ist ein Arbeitsbeispiel:
Verhindern Sie das Binden / Auslösen mehrerer Ereignisse
jQuery Mobile
funktioniert anders als klassische Webanwendungen. Abhängig davon, wie Sie es geschafft haben, Ihre Ereignisse bei jedem Besuch einer Seite zu binden, werden Ereignisse immer wieder gebunden. Dies ist kein Fehler, sondern lediglich der UmgangjQuery Mobile
mit den Seiten. Schauen Sie sich zum Beispiel dieses Code-Snippet an:Beispiel für ein funktionierendes jsFiddle: http://jsfiddle.net/Gajotres/CCfL4/
Jedes Mal, wenn Sie das Ereignis #index click auf Seite # besuchen, wird es an die Schaltfläche # test-button gebunden . Testen Sie es, indem Sie mehrmals von Seite 1 zu Seite 2 und zurück wechseln. Es gibt nur wenige Möglichkeiten, um dieses Problem zu vermeiden:
Lösung 1
Die beste Lösung wäre,
pageinit
Ereignisse zu binden. Wenn Sie sich eine offizielle Dokumentation ansehen, werden Sie feststellen, dasspageinit
sie NUR einmal ausgelöst wird, genau wie das Dokument, sodass Ereignisse auf keinen Fall erneut gebunden werden können. Dies ist die beste Lösung, da Sie keinen Verarbeitungsaufwand haben, wie beim Entfernen von Ereignissen mit der Off-Methode.Beispiel für ein funktionierendes jsFiddle: http://jsfiddle.net/Gajotres/AAFH8/
Diese Arbeitslösung basiert auf einem früheren problematischen Beispiel.
Lösung 2
Entfernen Sie das Ereignis, bevor Sie es binden:
Beispiel für ein funktionierendes jsFiddle: http://jsfiddle.net/Gajotres/K8YmG/
Lösung 3
Verwenden Sie einen jQuery-Filter-Selektor wie folgt:
Da der Ereignisfilter nicht Teil des offiziellen jQuery-Frameworks ist, finden Sie ihn hier: http://www.codenothing.com/archives/2009/event-filter/
Kurz gesagt, wenn Geschwindigkeit Ihr Hauptanliegen ist, ist Lösung 2 viel besser als Lösung 1.
Lösung 4
Ein neuer, wahrscheinlich der einfachste von allen.
Beispiel für ein funktionierendes jsFiddle: http://jsfiddle.net/Gajotres/Yerv9/
Vielen Dank an den Sholsinger für diese Lösung: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
pageChange-Ereignismacken - zweimaliges Auslösen
Manchmal kann ein Seitenwechselereignis zweimal ausgelöst werden und hat nichts mit dem zuvor erwähnten Problem zu tun.
Der Grund, warum das Ereignis pagebeforechange zweimal auftritt, ist der rekursive Aufruf in changePage, wenn toPage kein jQuery-erweitertes DOM-Objekt ist. Diese Rekursion ist gefährlich, da der Entwickler die toPage innerhalb des Ereignisses ändern darf. Wenn der Entwickler konsistent toPage auf eine Zeichenfolge setzt, wird innerhalb des Ereignishandlers pagebeforechange unabhängig davon, ob es sich um ein Objekt handelt oder nicht, eine unendliche rekursive Schleife erstellt. Das pageload-Ereignis übergibt die neue Seite als Seiteneigenschaft des Datenobjekts (Dies sollte der Dokumentation hinzugefügt werden, es ist derzeit nicht aufgeführt). Das pageload-Ereignis kann daher verwendet werden, um auf die geladene Seite zuzugreifen.
In wenigen Worten geschieht dies, weil Sie zusätzliche Parameter über pageChange senden.
Beispiel:
Um dieses Problem zu beheben, verwenden Sie ein beliebiges Seitenereignis, das in der Übergangsreihenfolge für Seitenereignisse aufgeführt ist .
Seitenwechselzeiten
Wie bereits erwähnt, treten beim Wechsel von einer jQuery Mobile-Seite zu einer anderen in der Regel mehrere Ereignisse und nachfolgende Aktionen auf, indem Sie entweder auf einen Link zu einer anderen bereits im DOM vorhandenen jQuery Mobile-Seite klicken oder $ .mobile.changePage manuell aufrufen. Auf hoher Ebene treten folgende Aktionen auf:
Dies ist ein durchschnittlicher Benchmark für den Seitenübergang:
Laden und Verarbeiten von Seiten : 3 ms
Seitenverbesserung: 45 ms
Übergang: 604 ms
Gesamtzeit: 670 ms
* Diese Werte sind in Millisekunden angegeben.
Wie Sie sehen, verbraucht ein Übergangsereignis fast 90% der Ausführungszeit.
Daten- / Parametermanipulation zwischen Seitenübergängen
Es ist möglich, während des Seitenübergangs einen oder mehrere Parameter von einer Seite zur anderen zu senden. Dies kann auf verschiedene Arten geschehen.
Referenz: https://stackoverflow.com/a/13932240/1848600
Lösung 1:
Sie können Werte mit changePage übergeben:
Und lies sie so:
Beispiel :
index.html
second.html
Lösung 2:
Oder Sie können ein dauerhaftes JavaScript-Objekt für einen Speicherzweck erstellen. Solange Ajax zum Laden von Seiten verwendet wird (und die Seite in keiner Weise neu geladen wird), bleibt dieses Objekt aktiv.
Beispiel: http://jsfiddle.net/Gajotres/9KKbx/
Lösung 3:
Sie können auch wie folgt auf Daten von der vorherigen Seite zugreifen:
Das prevPage- Objekt enthält eine vollständige vorherige Seite.
Lösung 4:
Als letzte Lösung haben wir eine raffinierte HTML-Implementierung von localStorage. Es funktioniert nur mit HTML5-Browsern (einschließlich Android- und iOS-Browsern), aber alle gespeicherten Daten bleiben durch Seitenaktualisierung erhalten.
Beispiel: http://jsfiddle.net/Gajotres/J9NTr/
Wahrscheinlich die beste Lösung, aber sie wird in einigen Versionen von iOS 5.X fehlschlagen. Es ist ein bekannter Fehler.
Verwenden Sie nicht
.live()
/.bind()
/.delegate()
Ich habe vergessen zu erwähnen (und tnx andleer, um mich daran zu erinnern), dass Ein / Aus für das Binden / Entbinden von Ereignissen, Live / Die und Binden / Entbinden veraltet sind.
Die .live () -Methode von jQuery wurde als Glücksfall angesehen, als sie in Version 1.3 in die API eingeführt wurde. In einer typischen jQuery-App kann es zu vielen DOM-Manipulationen kommen, und es kann sehr mühsam werden, beim Ein- und Aussteigen von Elementen ein- und auszuhängen. Die
.live()
Methode ermöglichte es, ein Ereignis für die Lebensdauer der App basierend auf ihrer Auswahl zu verknüpfen. Großartig, oder? Falsch, die.live()
Methode ist extrem langsam. Die.live()
Methode verknüpft ihre Ereignisse tatsächlich mit dem Dokumentobjekt. Dies bedeutet, dass das Ereignis aus dem Element, das das Ereignis generiert hat, sprudeln muss, bis es das Dokument erreicht. Dies kann erstaunlich zeitaufwändig sein.Es ist jetzt veraltet. Die Leute im jQuery-Team empfehlen die Verwendung nicht mehr und ich auch nicht. Auch wenn das Ein- und Aushängen von Ereignissen mühsam sein kann, ist Ihr Code ohne die
.live()
Methode viel schneller als mit dieser.Anstelle von
.live()
sollten Sie verwenden.on()
..on()
ist ungefähr 2-3x schneller als .live () . Schauen Sie sich diesen ereignisbindenden Benchmark an: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , von dort aus wird alles klar.Benchmarking:
Es gibt ein hervorragendes Skript für das Benchmarking von jQuery Mobile- Seitenereignissen. Es kann hier gefunden werden: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Bevor Sie jedoch etwas damit anfangen, empfehle ich Ihnen, das
alert
Benachrichtigungssystem zu entfernen (jede „Änderungsseite“ zeigt Ihnen diese Daten an, indem Sie die App anhalten) und sie in dieconsole.log
Funktion zu ändern .Grundsätzlich protokolliert dieses Skript alle Ihre Seitenereignisse. Wenn Sie diesen Artikel sorgfältig lesen (Beschreibungen der Seitenereignisse), wissen Sie, wie viel Zeit jQm für Seitenverbesserungen, Seitenübergänge usw. aufgewendet hat.
Schlussbemerkungen
Lesen Sie immer die offizielle jQuery Mobile- Dokumentation. In der Regel erhalten Sie die erforderlichen Informationen, und im Gegensatz zu anderen Dokumentationen ist diese ziemlich gut, mit genügend Erklärungen und Codebeispielen.
Änderungen:
quelle
$().live()
wurde in jQuery 1.7 abgeschrieben und in 1.9 entfernt, sodass es wirklich Teil jeder jQuery Mobile-Lösung sein sollte. Die aktuelle Mindestkernversion für jQM 1.7.pagecreate
Das Ereignis wird nur einmal ausgelöst, wenn die Seite zum ersten Mal erstellt wird. Wenn wir also Klickereignisse binden, wirdpagecreate
es nicht mehrmals ausgelöst. Etwas, das ich bei der Entwicklung der App herausgefunden habe. Wir können jedoch nicht immerpagecreate
Ereignisse binden, sodass die von Ihnen angegebene Lösung die beste ist. +1 gegebenEinige von Ihnen finden dies möglicherweise hilfreich. Kopieren Sie es einfach und fügen Sie es in Ihre Seite ein. Sie erhalten eine Reihenfolge, in der Ereignisse in der Chrome-Konsole ausgelöst werden ( Ctrl+ Shift+ I).
In der Konsole wird kein Entladen angezeigt, da diese beim Entladen der Seite ausgelöst wird (wenn Sie sich von der Seite entfernen). Verwenden Sie es so:
Und du wirst sehen, was ich meine.
quelle
Das ist der richtige Weg:
Um Code auszuführen, der nur für die Indexseite verfügbar ist, können wir diese Syntax verwenden:
quelle
Der einfache Unterschied zwischen Dokumentbereitschaft und Seitenereignis in jQuery-mobile besteht darin, dass:
Das Dokument Ready-Ereignis wird für die gesamte HTML-Seite verwendet.
Wenn es ein Seitenereignis gibt, verwenden Sie es zur Behandlung eines bestimmten Seitenereignisses:
Sie können das Dokument auch zur Behandlung des pageinit-Ereignisses verwenden:
quelle
Während Sie .on () verwenden, handelt es sich im Grunde genommen um eine Live-Abfrage, die Sie verwenden.
Auf der anderen Seite ist .ready (wie in Ihrem Fall) eine statische Abfrage. Während der Verwendung können Sie Daten dynamisch aktualisieren und müssen nicht auf das Laden der Seite warten. Sie können die Werte einfach (falls erforderlich) an Ihre Datenbank weitergeben, wenn ein bestimmter Wert eingegeben wird.
Die Verwendung von Live-Abfragen ist in Formularen üblich, in denen wir Daten eingeben (Konto oder Beiträge oder sogar Kommentare).
quelle