Korzystam z jQuery Mobile i mam problem ze zrozumieniem różnic między klasycznymi przygotowaniami dokumentów a zdarzeniami strony jQuery Mobile.
Jaka jest prawdziwa różnica?
Dlaczego powinieneś
<!-- language: lang-js --> $(document).ready() { });
być lepszym niż
$(document).on('pageinit') { });
Jaka jest kolejność zdarzeń na stronie, kiedy przechodzisz z jednej strony na drugą?
Jak mogę wysyłać dane z jednej strony na drugą i czy można uzyskać dostęp do danych z poprzedniej strony?
javascript
jquery
html
jquery-mobile
cordova
użytkownik2001897
źródło
źródło
Odpowiedzi:
Aktualizacja jQuery Mobile 1.4:
Mój oryginalny artykuł był przeznaczony do starego sposobu obsługi strony, w zasadzie wszystkiego przed jQuery Mobile 1.4. Stary sposób obsługi jest już przestarzały i pozostanie aktywny do (włącznie) jQuery Mobile 1.5, więc możesz nadal korzystać ze wszystkiego, co wspomniano poniżej, przynajmniej do przyszłego roku i jQuery Mobile 1.6.
Stare zdarzenia, w tym pageinit , już nie istnieją, są one zastąpione widżetem pojemnika do przechowywania . Pageinit został całkowicie usunięty i zamiast tego można użyć funkcji tworzenia kopii , zdarzenie pozostało takie samo i nie będzie zmieniane.
Jeśli jesteś zainteresowany nowym sposobem obsługi zdarzeń na stronie, zajrzyj tutaj , w każdym innym przypadku zachęcamy do kontynuowania tego artykułu. Powinieneś przeczytać tę odpowiedź, nawet jeśli używasz jQuery Mobile 1.4 +, wykracza ona poza zdarzenia na stronie, więc prawdopodobnie znajdziesz wiele przydatnych informacji.
Starsze treści:
Ten artykuł można również znaleźć w ramach mojego bloga TUTAJ .
$(document).on('pageinit')
vs$(document).ready()
Pierwszą rzeczą, której uczysz się w jQuery, jest wywoływanie kodu wewnątrz
$(document).ready()
funkcji, aby wszystko wykonało się po załadowaniu DOM. Jednak w jQuery Mobile Ajax służy do ładowania zawartości każdej strony do DOM podczas nawigacji. Z tego powodu$(document).ready()
uruchomi się przed załadowaniem pierwszej strony, a każdy kod przeznaczony do manipulacji stroną zostanie wykonany po odświeżeniu strony. Może to być bardzo subtelny błąd. W niektórych systemach może się wydawać, że działa dobrze, ale w innych może powodować nieregularne, trudne do powtórzenia dziwności.Klasyczna składnia jQuery:
Aby rozwiązać ten problem (i zaufaj mi, to jest problem) programiści jQuery Mobile stworzyli zdarzenia strony. W skrócie zdarzenia strony to zdarzenia uruchamiane w danym punkcie wykonania strony. Jednym z takich zdarzeń na stronie jest zdarzenie pageinit , którego możemy użyć w następujący sposób:
Możemy pójść jeszcze dalej i użyć identyfikatora strony zamiast selektora dokumentów. Załóżmy, że mamy stronę jQuery Mobile z indeksem identyfikatora :
Aby wykonać kod, który będzie dostępny tylko dla strony indeksu, możemy użyć tej składni:
Zdarzenie Pageinit będzie wykonywane za każdym razem, gdy strona będzie ładowana i pokazywana po raz pierwszy. Nie uruchomi się ponownie, chyba że strona zostanie ręcznie odświeżona lub ładowanie strony Ajax zostanie wyłączone. Jeśli chcesz, aby kod był wykonywany za każdym razem, gdy odwiedzasz stronę, lepiej użyć zdarzenia pagebeforeshow .
Oto działający przykład: http://jsfiddle.net/Gajotres/Q3Usv/, aby zademonstrować ten problem.
Jeszcze kilka notatek na to pytanie. Bez względu na to, czy używasz 1 html wielu stron, czy paradygmatu wielu plików HTML, zaleca się rozdzielenie wszystkich niestandardowych metod obsługi stron JavaScript na jeden osobny plik JavaScript. Zauważy to, że twój kod będzie lepszy, ale będziesz miał znacznie lepszy przegląd kodu, szczególnie podczas tworzenia aplikacji jQuery Mobile .
Jest też inne specjalne wydarzenie jQuery Mobile, które nazywa się mobileinit . Po uruchomieniu jQuery Mobile wyzwala zdarzenie mobileinit na obiekcie dokumentu. Aby zastąpić ustawienia domyślne, powiąż je z mobileinit . Jednym z dobrych przykładów użycia mobileinit jest wyłączenie ładowania strony Ajax lub zmiana domyślnego zachowania modułu ładującego Ajax.
Kolejność przejścia zdarzeń strony
Po pierwsze wszystkie wydarzenia można znaleźć tutaj: http://api.jquerymobile.com/category/events/
Powiedzmy, że mamy stronę A i stronę B, jest to kolejność rozładowywania / ładowania:
strona B - strona zdarzenia przed utworzeniem
Strona B - zdarzenie pagecreate
Strona B - zdarzenie pageinit
strona A - strona zdarzenia przed ukryciem
strona A - usunięcie strony zdarzenia
strona A - zdarzenie pagehide
strona B - strona wydarzenia przed odświeżeniem
strona B - pokaz stron wydarzenia
Aby lepiej zrozumieć zdarzenia na stronie, przeczytaj to:
pagebeforeload
,pageload
Ipageloadfailed
są wypalane, gdy strona zewnętrzna jest ładowanypagebeforechange
,pagechange
Ipagechangefailed
są strona wydarzenia zmieniają. Te zdarzenia są uruchamiane, gdy użytkownik porusza się między stronami w aplikacjach.pagebeforeshow
,pagebeforehide
,pageshow
Ipagehide
są strona wydarzenia przejściowe. Te zdarzenia są uruchamiane przed przejściem, w trakcie i po przejściu i są nazywane.pagebeforecreate
,pagecreate
Ipageinit
są na stronie inicjalizacji.pageremove
można uruchomić, a następnie obsłużyć, gdy strona zostanie usunięta z DOMPrzykład ładowania strony jsFiddle: http://jsfiddle.net/Gajotres/QGnft/
Zapobiegaj przenoszeniu stron
Jeśli z jakiegoś powodu konieczne jest uniemożliwienie przejścia strony pod pewnym warunkiem, można to zrobić za pomocą tego kodu:
Ten przykład zadziała w każdym przypadku, ponieważ uruchomi się na początku każdego przejścia strony, a co najważniejsze, zapobiegnie zmianie strony przed przejściem strony.
Oto działający przykład:
Zapobiegaj wiązaniu / wyzwalaniu wielu zdarzeń
jQuery Mobile
działa w inny sposób niż klasyczne aplikacje internetowe. W zależności od tego, w jaki sposób udało Ci się powiązać wydarzenia za każdym razem, gdy odwiedzasz stronę, będzie ona wiązać wydarzenia w kółko. To nie jest błąd, to po prostu sposóbjQuery Mobile
obsługi jego stron. Na przykład spójrz na ten fragment kodu:Przykład działającego jsFiddle: http://jsfiddle.net/Gajotres/CCfL4/
Za każdym razem, gdy odwiedzasz stronę, # kliknięcie indeksu będzie przypisane do przycisku # przycisk testu . Przetestuj go, przechodząc kilkakrotnie ze strony 1 na stronę 2 i wstecz. Istnieje kilka sposobów zapobiegania temu problemowi:
Rozwiązanie 1
Najlepszym rozwiązaniem byłoby
pageinit
powiązanie zdarzeń. Jeśli spojrzysz na oficjalną dokumentację, przekonasz się, żepageinit
uruchomi się TYLKO raz, tak jak dokument gotowy, więc nie ma możliwości, aby zdarzenia zostały ponownie powiązane. Jest to najlepsze rozwiązanie, ponieważ nie ma narzutów związanych z przetwarzaniem, takich jak usuwanie zdarzeń metodą wyłączoną.Przykład działającego jsFiddle: http://jsfiddle.net/Gajotres/AAFH8/
To robocze rozwiązanie zostało wykonane na podstawie poprzedniego problematycznego przykładu.
Rozwiązanie 2
Usuń zdarzenie przed powiązaniem:
Przykład działającego jsFiddle: http://jsfiddle.net/Gajotres/K8YmG/
Rozwiązanie 3
Użyj selektora filtru jQuery, takiego jak ten:
Ponieważ filtr zdarzeń nie jest częścią oficjalnej struktury jQuery, można go znaleźć tutaj: http://www.codenothing.com/archives/2009/event-filter/
W skrócie, jeśli głównym problemem jest szybkość, to Rozwiązanie 2 jest znacznie lepsze niż Rozwiązanie 1.
Rozwiązanie 4
Nowy, prawdopodobnie najłatwiejszy ze wszystkich.
Przykład działającego jsFiddle: http://jsfiddle.net/Gajotres/Yerv9/
Tnx do sholsinger dla tego rozwiązania: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
pageChange zdarzenia dziwactwa - wyzwalanie dwa razy
Czasami zdarzenie zmiany strony może zostać uruchomione dwukrotnie i nie ma to nic wspólnego z wyżej wymienionym problemem.
Powodem, dla którego zdarzenie pagebeforechange występuje dwukrotnie, jest wywołanie rekurencyjne w changePage, gdy toPage nie jest obiektem DOM wzbogaconym o jQuery. Ta rekurencja jest niebezpieczna, ponieważ programista może zmienić stronę na stronę w ramach zdarzenia. Jeśli programista konsekwentnie ustawia wartość toPage na ciąg znaków, w procedurze obsługi zdarzeń pagebeforechange, niezależnie od tego, czy był to obiekt, powstanie nieskończona pętla rekurencyjna. Zdarzenie pageload przekazuje nową stronę jako właściwość strony obiektu danych (należy ją dodać do dokumentacji, obecnie jej nie ma na liście). Zdarzenie pageload może zatem zostać wykorzystane do uzyskania dostępu do załadowanej strony.
W kilku słowach dzieje się tak, ponieważ przesyłasz dodatkowe parametry przez pageChange.
Przykład:
Aby rozwiązać ten problem, użyj dowolnego zdarzenia strony wymienionego w kolejności przejścia zdarzeń strony .
Czas zmiany strony
Jak wspomniano, po przejściu z jednej strony jQuery Mobile na inną, zazwyczaj albo poprzez kliknięcie łącza do innej strony jQuery Mobile, która już istnieje w DOM, lub przez ręczne wywołanie $ .mobile.changePage, następuje kilka zdarzeń i kolejne działania. Na wysokim poziomie występują następujące działania:
Jest to średni test przejścia strony:
Ładowanie strony i przetwarzanie: 3 ms
Ulepszenie strony: 45 ms
Przejście: 604 ms
Całkowity czas: 670 ms
* Te wartości są w milisekundach.
Jak widać, zdarzenie przejścia pochłania prawie 90% czasu wykonania.
Manipulowanie danymi / parametrami między przejściami stron
Możliwe jest przesyłanie parametrów z jednej strony na drugą podczas przejścia strony. Można to zrobić na kilka sposobów.
Odniesienie: https://stackoverflow.com/a/13932240/1848600
Rozwiązanie 1:
Możesz przekazać wartości za pomocą changePage:
I przeczytaj je w ten sposób:
Przykład :
index.html
second.html
Rozwiązanie 2:
Możesz też utworzyć trwały obiekt JavaScript do celów przechowywania. Dopóki Ajax jest używany do ładowania strony (a strona nie jest w żaden sposób przeładowywana), obiekt ten pozostanie aktywny.
Przykład: http://jsfiddle.net/Gajotres/9KKbx/
Rozwiązanie 3:
Możesz również uzyskać dostęp do danych z poprzedniej strony w następujący sposób:
Obiekt prevPage zawiera całą poprzednią stronę.
Rozwiązanie 4:
Jako ostatnie rozwiązanie mamy sprytną implementację HTML localStorage. Działa tylko z przeglądarkami HTML5 (w tym z przeglądarkami Android i iOS), ale wszystkie przechowywane dane są trwałe przez odświeżanie strony.
Przykład: http://jsfiddle.net/Gajotres/J9NTr/
Prawdopodobnie najlepsze rozwiązanie, ale zawiedzie w niektórych wersjach iOS 5.X. To dobrze znany błąd.
Nie używaj
.live()
/.bind()
/.delegate()
Zapomniałem wspomnieć (i tnx andleer dla przypomnienia mi) użycie włączania / wyłączania do wiązania / cofania powiązania zdarzeń, live / die i bind / unbind są przestarzałe.
Metoda jQuery .live () była postrzegana jako dar niebios, kiedy została wprowadzona do API w wersji 1.3. W typowej aplikacji jQuery może istnieć wiele manipulacji DOM i przechwytywanie i odczepianie może być bardzo uciążliwe, gdy elementy pojawiają się i znikają. Ta
.live()
metoda umożliwiła przechwycenie zdarzenia przez cały czas działania aplikacji na podstawie jej selektora. Świetnie prawda? Źle,.live()
metoda jest bardzo powolna..live()
Metoda rzeczywiście haki jego zdarzeń do obiektu dokumentu, co oznacza, że bańka musi wydarzenie się z elementu, który wygenerował zdarzenie, aż osiągnie dokument. Może to być niezwykle czasochłonne.To jest teraz przestarzałe. Ludzie w zespole jQuery nie zalecają już jego użycia i ja też tego nie robią. Mimo że przechwytywanie i odczepianie zdarzeń może być żmudne, kod będzie znacznie szybszy bez tej
.live()
metody niż z nią.Zamiast tego
.live()
powinieneś użyć.on()
..on()
jest około 2-3 razy szybszy niż .live () . Spójrz na to wiążące kryterium odniesienia dla wydarzenia: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , wszystko będzie jasne.Benchmarking:
Istnieje doskonały skrypt do testów porównawczych zdarzeń stron jQuery Mobile . Można go znaleźć tutaj: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Ale zanim cokolwiek z tym zrobisz, radzę usunąć
alert
system powiadomień (każda „strona zmiany” pokaże te dane, zatrzymując aplikację) i zmienić ją naconsole.log
działającą.Zasadniczo ten skrypt rejestruje wszystkie zdarzenia na stronie, a jeśli dokładnie przeczytasz ten artykuł (opisy zdarzeń na stronie), będziesz wiedział, ile czasu spędził jQm na ulepszenia strony, przejścia stron ...
Uwagi końcowe
Zawsze i mam na myśli zawsze czytać oficjalną dokumentację jQuery Mobile . Zwykle dostarcza potrzebnych informacji, w przeciwieństwie do innych dokumentów, ta jest raczej dobra, z wystarczającą ilością wyjaśnień i przykładów kodu.
Zmiany:
źródło
$().live()
został amortyzowany w jQuery 1.7 i usunięty w 1.9, więc naprawdę powinien być częścią każdego rozwiązania jQuery Mobile. Aktualna minimalna wersja jądra dla jQM 1.7.pagecreate
zdarzenie jest uruchamiane tylko raz, gdy strona została utworzona po raz pierwszy. więc jeśli powiązamy zdarzenia kliknięcia w środku,pagecreate
nie będą uruchamiane wiele razy. Coś wymyśliłem podczas tworzenia aplikacji. Ale nie zawsze możemy używaćpagecreate
do wiązania zdarzeń, więc podane rozwiązanie jest najlepsze. Dano +1Niektórzy z was mogą uznać to za przydatne. Po prostu skopiuj i wklej na swoją stronę, a otrzymasz sekwencję, w której zdarzenia są uruchamiane w konsoli Chrome ( Ctrl+ Shift+ I).
Nie będzie widać rozładowania w konsoli, ponieważ jest ona uruchamiana podczas rozładowywania strony (po odejściu od strony). Użyj tego w ten sposób:
I zobaczysz, co mam na myśli.
źródło
To jest właściwy sposób:
Aby wykonać kod, który będzie dostępny tylko dla strony indeksu, możemy użyć tej składni:
źródło
Prosta różnica między przygotowaniem dokumentu a zdarzeniem strony w jQuery-mobile polega na tym, że:
Zdarzenie gotowości dokumentu jest używane dla całej strony HTML,
Gdy występuje zdarzenie strony, użyj go do obsługi określonego zdarzenia strony:
Możesz także użyć dokumentu do obsługi zdarzenia pageinit:
źródło
Podczas używania .on () jest to w zasadzie zapytanie aktywne.
Z drugiej strony .ready (jak w twoim przypadku) jest zapytaniem statycznym. Podczas jego używania możesz dynamicznie aktualizować dane i nie musisz czekać na załadowanie strony. Możesz po prostu przekazać wartości do bazy danych (jeśli jest to wymagane) po wprowadzeniu określonej wartości.
Korzystanie z zapytań na żywo jest powszechne w formularzach, w których wprowadzamy dane (konto lub posty, a nawet komentarze).
źródło