Pembaruan jQuery Mobile 1.4:
Artikel asli saya dimaksudkan untuk cara penanganan halaman yang lama, pada dasarnya segalanya sebelum jQuery Mobile 1.4. Cara penanganan lama sekarang sudah usang dan akan tetap aktif sampai (termasuk) jQuery Mobile 1.5, sehingga Anda masih dapat menggunakan semua yang disebutkan di bawah ini, setidaknya sampai tahun depan dan jQuery Mobile 1.6.
Acara lama, termasuk pageinit tidak ada lagi, mereka diganti dengan widget pagecontainer . Pageinit terhapus sepenuhnya dan Anda dapat menggunakan pagecreate sebagai gantinya, acara itu tetap sama dan tidak akan diubah.
Jika Anda tertarik dengan cara baru penanganan acara halaman lihat di sini , dalam hal lain merasa bebas untuk melanjutkan dengan artikel ini. Anda harus membaca jawaban ini bahkan jika Anda menggunakan jQuery Mobile 1.4 +, itu melampaui peristiwa halaman sehingga Anda mungkin akan menemukan banyak informasi yang berguna.
Konten yang lebih lama:
Artikel ini juga dapat ditemukan sebagai bagian dari blog saya DI SINI .
$(document).on('pageinit')
vs. $(document).ready()
Hal pertama yang Anda pelajari di jQuery adalah memanggil kode di dalam $(document).ready()
fungsi sehingga semuanya akan dijalankan segera setelah DOM dimuat. Namun, di jQuery Mobile , Ajax digunakan untuk memuat konten setiap halaman ke DOM saat Anda menavigasi. Karena ini $(document).ready()
akan memicu sebelum halaman pertama Anda dimuat dan setiap kode yang dimaksudkan untuk manipulasi halaman akan dieksekusi setelah refresh halaman. Ini bisa menjadi bug yang sangat halus. Pada beberapa sistem mungkin terlihat berfungsi dengan baik, tetapi pada yang lain mungkin menyebabkan keanehan, sulit untuk mengulangi keanehan terjadi.
Sintaks jQuery klasik:
$(document).ready(function() {
});
Untuk mengatasi masalah ini (dan percayalah ini masalah), pengembang jQuery Mobile membuat acara laman. Singkatnya, acara adalah peristiwa yang dipicu pada titik tertentu dari eksekusi halaman. Salah satu acara halaman tersebut adalah acara pageinit dan kita dapat menggunakannya seperti ini:
$(document).on('pageinit', function() {
});
Kita dapat melangkah lebih jauh dan menggunakan id halaman alih-alih pemilih dokumen. Katakanlah kita memiliki halaman jQuery Mobile dengan indeks id :
<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>
Untuk mengeksekusi kode yang hanya akan tersedia untuk halaman indeks kita bisa menggunakan sintaks ini:
$('#index').on('pageinit', function() {
});
Acara Pageinit akan dieksekusi setiap halaman waktu akan dimuat dan ditampilkan untuk pertama kalinya. Itu tidak akan memicu lagi kecuali halaman di-refresh secara manual atau memuat halaman Ajax dimatikan. Jika Anda ingin kode dijalankan setiap kali Anda mengunjungi halaman, lebih baik menggunakan acara pagebeforeshow .
Berikut ini contoh yang berfungsi: http://jsfiddle.net/Gajotres/Q3Usv/ untuk mendemonstrasikan masalah ini.
Lebih sedikit catatan tentang pertanyaan ini. Tidak masalah jika Anda menggunakan 1 html banyak halaman atau beberapa paradigma file HTML, disarankan untuk memisahkan semua penanganan halaman JavaScript khusus Anda menjadi satu file JavaScript terpisah. Ini akan mencatat membuat kode Anda lebih baik tetapi Anda akan memiliki gambaran umum kode yang lebih baik, terutama saat membuat aplikasi jQuery Mobile .
Ada juga acara jQuery Mobile khusus dan disebut mobileinit . Ketika jQuery Mobile mulai, itu memicu acara mobileinit pada objek dokumen. Untuk mengganti pengaturan default, ikatkan ke mobileinit . Salah satu contoh yang baik dari penggunaan mobileinit adalah mematikan pemuatan halaman Ajax, atau mengubah perilaku loader Ajax default.
$(document).on("mobileinit", function(){
//apply overrides here
});
Urutan transisi acara laman
Pertama semua acara dapat ditemukan di sini: http://api.jquerymobile.com/category/events/
Katakanlah kita memiliki halaman A dan halaman B, ini adalah perintah bongkar / muat:
halaman B - acara pagebeforecreate
halaman B - pagecreate acara
halaman B - pageinit acara
halaman A - acara pagebeforehide
halaman A - pageremove event
halaman A - eventhidehide
halaman B - acara pagebeforeshow
halaman B - pageshow acara
Untuk pemahaman acara laman yang lebih baik baca ini:
pagebeforeload
, pageload
dan pageloadfailed
dipecat ketika halaman eksternal dimuat
pagebeforechange
, pagechange
dan pagechangefailed
acara perubahan halaman. Peristiwa ini dipecat ketika pengguna menavigasi antara halaman dalam aplikasi.
pagebeforeshow
, pagebeforehide
, pageshow
Dan pagehide
adalah halaman peristiwa transisi. Peristiwa ini dipecat sebelum, selama dan setelah transisi dan diberi nama.
pagebeforecreate
, pagecreate
dan pageinit
untuk inisialisasi halaman.
pageremove
dapat dipecat dan kemudian ditangani ketika halaman dihapus dari DOM
Pemuatan halaman contoh jsFiddle: http://jsfiddle.net/Gajotres/QGnft/
Jika AJAX tidak diaktifkan, beberapa acara mungkin tidak menyala.
Cegah transisi halaman
Jika karena alasan tertentu transisi halaman perlu dicegah dengan syarat tertentu dapat dilakukan dengan kode ini:
$(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');;
}
}
});
Contoh ini akan berfungsi dalam hal apa pun karena akan memicu permintaan setiap transisi halaman dan yang paling penting itu akan mencegah perubahan halaman sebelum transisi halaman dapat terjadi.
Berikut ini contoh kerjanya:
Cegah beberapa peristiwa mengikat / memicu
jQuery Mobile
bekerja dengan cara yang berbeda dari aplikasi web klasik. Tergantung pada bagaimana Anda berhasil mengikat acara Anda setiap kali Anda mengunjungi beberapa halaman itu akan mengikat acara berulang-ulang. Ini bukan kesalahan, itu hanya bagaimana jQuery Mobile
menangani halaman-halamannya. Misalnya, lihat cuplikan kode ini:
$(document).on('pagebeforeshow','#index' ,function(e,data){
$(document).on('click', '#test-button',function(e) {
alert('Button click');
});
});
Bekerja jsFiddle contoh: http://jsfiddle.net/Gajotres/CCfL4/
Setiap kali Anda mengunjungi halaman acara #index klik akan terikat ke tombol # uji-tombol . Cobalah dengan berpindah dari halaman 1 ke halaman 2 dan kembali beberapa kali. Ada beberapa cara untuk mencegah masalah ini:
Solusi 1
Solusi terbaik akan digunakan pageinit
untuk mengikat acara. Jika Anda melihat pada dokumentasi resmi Anda akan menemukan bahwa pageinit
HANYA akan memicu sekali, sama seperti dokumen siap, jadi tidak ada cara peristiwa akan terikat lagi. Ini adalah solusi terbaik karena Anda tidak memiliki pemrosesan overhead seperti ketika menghapus acara dengan metode mati.
Bekerja jsFiddle contoh: http://jsfiddle.net/Gajotres/AAFH8/
Solusi kerja ini dibuat berdasarkan contoh bermasalah sebelumnya.
Solusi 2
Hapus acara sebelum Anda mengikatnya:
$(document).on('pagebeforeshow', '#index', function(){
$(document).off('click', '#test-button').on('click', '#test-button',function(e) {
alert('Button click');
});
});
Bekerja jsFiddle contoh: http://jsfiddle.net/Gajotres/K8YmG/
Solusi 3
Gunakan pemilih Filter jQuery, seperti ini:
$('#carousel div:Event(!click)').each(function(){
//If click is not bind to #carousel div do something
});
Karena filter acara bukan bagian dari kerangka kerja jQuery resmi, filter ini dapat ditemukan di sini: http://www.codenothing.com/archives/2009/event-filter/
Singkatnya, jika kecepatan adalah perhatian utama Anda maka Solusi 2 jauh lebih baik daripada Solusi 1.
Solusi 4
Yang baru, mungkin yang termudah dari semuanya.
$(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;
}
});
});
Bekerja jsFiddle contoh: http://jsfiddle.net/Gajotres/Yerv9/
Tnx ke sholsinger untuk solusi ini: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
pageChange acara quirks - memicu dua kali
Terkadang acara pagechange dapat memicu dua kali dan tidak ada hubungannya dengan masalah yang disebutkan sebelumnya.
Alasan acara pagebeforechange terjadi dua kali adalah karena panggilan rekursif di changePage ketika toPage bukan objek DOM yang ditingkatkan jQuery. Rekursi ini berbahaya, karena pengembang diizinkan mengubah toPage dalam acara tersebut. Jika pengembang secara konsisten menetapkan toPage ke string, di dalam event handler pagebeforechange, terlepas dari apakah itu objek atau tidak, loop rekursif tak terbatas akan dihasilkan. Acara pageload melewati halaman baru sebagai properti halaman dari objek data (Ini harus ditambahkan ke dokumentasi, itu tidak terdaftar saat ini). Acara pageload dapat digunakan untuk mengakses halaman yang dimuat.
Dalam beberapa kata ini terjadi karena Anda mengirim parameter tambahan melalui pageChange.
Contoh:
<a data-role="button" data-icon="arrow-r" data-iconpos="right" href="#care-plan-view?id=9e273f31-2672-47fd-9baa-6c35f093a800&name=Sat"><h3>Sat</h3></a>
Untuk memperbaiki masalah ini, gunakan setiap peristiwa halaman yang tercantum dalam urutan transisi peristiwa Halaman .
Waktu Ubah Halaman
Seperti disebutkan, ketika Anda mengubah dari satu halaman jQuery Mobile ke yang lain, biasanya melalui mengklik tautan ke halaman jQuery Mobile lain yang sudah ada di DOM, atau dengan secara manual menelepon $ .mobile.changePage, beberapa peristiwa dan tindakan selanjutnya terjadi. Pada tingkat tinggi, tindakan berikut terjadi:
- Proses perubahan halaman dimulai
- Halaman baru dimuat
- Konten untuk halaman itu “disempurnakan” (ditata)
- Terjadi transisi (slide / pop / etc) dari halaman yang ada ke halaman baru
Ini adalah tolok ukur transisi halaman rata-rata:
Pemuatan dan pemrosesan halaman: 3 ms
Peningkatan halaman: 45 ms
Transisi: 604 ms
Total waktu: 670 ms
* Nilai-nilai ini dalam milidetik.
Jadi seperti yang Anda lihat, acara transisi memakan hampir 90% waktu eksekusi.
Manipulasi data / parameter antara transisi halaman
Dimungkinkan untuk mengirim parameter dari satu halaman ke halaman lain selama transisi halaman. Itu bisa dilakukan dengan beberapa cara.
Referensi: https://stackoverflow.com/a/13932240/1848600
Solusi 1:
Anda bisa memberikan nilai dengan changePage:
$.mobile.changePage('page2.html', { dataUrl : "page2.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : true, changeHash : true });
Dan baca seperti ini:
$(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>
Solusi 2:
Atau Anda dapat membuat objek JavaScript persisten untuk tujuan penyimpanan. Selama Ajax digunakan untuk memuat halaman (dan halaman tidak dimuat ulang dengan cara apa pun) objek itu akan tetap aktif.
var storeObject = {
firstname : '',
lastname : ''
}
Contoh: http://jsfiddle.net/Gajotres/9KKbx/
Solusi 3:
Anda juga dapat mengakses data dari halaman sebelumnya seperti ini:
$(document).on('pagebeforeshow', '#index',function (e, data) {
alert(data.prevPage.attr('id'));
});
objek prevPage memegang halaman sebelumnya yang lengkap.
Solusi 4:
Sebagai solusi terakhir kami memiliki implementasi HTML yang bagus dari localStorage. Ini hanya bekerja dengan browser HTML5 (termasuk browser Android dan iOS) tetapi semua data yang disimpan tetap ada melalui penyegaran halaman.
if(typeof(Storage)!=="undefined") {
localStorage.firstname="Dragan";
localStorage.lastname="Gaic";
}
Contoh: http://jsfiddle.net/Gajotres/J9NTr/
Mungkin solusi terbaik tetapi akan gagal di beberapa versi iOS 5.X. Ini adalah kesalahan yang diketahui dengan baik.
Jangan gunakan .live()
/ .bind()
/.delegate()
Saya lupa menyebutkan (dan tnx andleer untuk mengingatkan saya) gunakan on / off untuk acara mengikat / tidak mengikat, hidup / mati dan bind / unbind sudah usang.
Metode .live () dari jQuery dilihat sebagai anugerah ketika diperkenalkan ke API di versi 1.3. Dalam aplikasi jQuery tipikal, ada banyak manipulasi DOM dan bisa sangat membosankan untuk mengait dan melepas kaitan ketika elemen datang dan pergi. The .live()
Metode memungkinkan untuk menghubungkan sebuah acara untuk kehidupan aplikasi berdasarkan pemilih nya. Bagus bukan? Salah, .live()
metode ini sangat lambat. The .live()
Metode sebenarnya kait acara untuk objek dokumen, yang berarti bahwa acara harus gelembung naik dari elemen yang dihasilkan acara hingga mencapai dokumen. Ini bisa memakan waktu yang luar biasa.
Sekarang sudah usang. Orang-orang di tim jQuery tidak lagi merekomendasikan penggunaannya dan saya juga tidak. Meskipun bisa membosankan untuk mengaitkan dan melepas kaitan peristiwa, kode Anda akan jauh lebih cepat tanpa .live()
metode daripada dengan menggunakannya.
Alih-alih .live()
Anda harus menggunakan .on()
. .on()
sekitar 2-3x lebih cepat dari .live () . Lihatlah benchmark mengikat acara ini: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , semuanya akan menjadi jelas dari sana.
Pembandingan:
Ada skrip luar biasa yang dibuat untuk pembandingan acara laman jQuery Mobile . Itu dapat ditemukan di sini: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Tetapi sebelum Anda melakukan sesuatu dengan itu saya menyarankan Anda untuk menghapus alert
sistem notifikasi (setiap "halaman perubahan" akan menunjukkan kepada Anda data ini dengan menghentikan aplikasi) dan mengubahnya console.log
berfungsi.
Pada dasarnya skrip ini akan mencatat semua peristiwa halaman Anda dan jika Anda membaca artikel ini dengan seksama (deskripsi acara halaman), Anda akan tahu berapa banyak waktu yang dihabiskan jQm untuk peningkatan halaman, transisi halaman ....
Catatan akhir
Selalu, dan maksud saya selalu membaca dokumentasi resmi jQuery Mobile . Biasanya akan memberi Anda informasi yang diperlukan, dan tidak seperti beberapa dokumentasi lain yang satu ini cukup baik, dengan cukup penjelasan dan contoh kode.
Perubahan:
- 30.01.2013 - Menambahkan metode baru pencegahan berbagai peristiwa yang memicu
- 31.01.2013 - Menambahkan klarifikasi yang lebih baik untuk manipulasi Data / Parameter bab antara transisi halaman
- 03.02.2013 - Menambahkan konten / contoh baru ke bab manipulasi Data / Parameter antara transisi halaman
- 22.05.2013 - Menambahkan solusi untuk transisi / pencegahan perubahan halaman dan menambahkan tautan ke dokumentasi peristiwa acara resmi API
- 18.05.2013 - Menambahkan solusi lain terhadap beberapa peristiwa yang mengikat