jQuery Mobile 1.4 Güncellemesi:
Orijinal makalem eski sayfa kullanımı, jQuery Mobile 1.4 öncesi her şey için tasarlanmıştır. Eski kullanım şekli artık kullanımdan kaldırılmıştır ve jQuery Mobile 1.5'e kadar (dahil) etkin kalacaktır, bu nedenle aşağıda belirtilen her şeyi, en azından gelecek yıla ve jQuery Mobile 1.6'ya kadar kullanabilirsiniz.
Pageinit dahil olmak üzere eski etkinlikler artık mevcut değil, bunların yerine pagecontainer widget'ı kullanılıyor. Pageinit tamamen silinir ve bunun yerine pagecreate kullanabilirsiniz , bu olay aynı kaldı ve değiştirilmeyecek.
Yeni sayfa etkinliği ile ilgileniyorsanız, olay işleme burada bir göz atın , başka bir durumda bu makaleye devam etmek için çekinmeyin. JQuery Mobile 1.4 + kullanıyor olsanız bile bu yanıtı okumalısınız, sayfa etkinliklerinin ötesine geçecektir, böylece muhtemelen birçok yararlı bilgi bulacaksınız.
Daha eski içerik:
Bu makale ayrıca blogumun bir parçası olarak BURADA bulunabilir .
$(document).on('pageinit')
vs $(document).ready()
JQuery'de öğrendiğiniz ilk şey , $(document).ready()
fonksiyon yüklendiğinde kodu çağırmaktır, böylece DOM yüklenir yüklenmez her şey yürütülür. Ancak, jQuery Mobile'da Ajax, her sayfanın içeriğini siz gezinirken DOM'a yüklemek için kullanılır. Bu nedenle, $(document).ready()
ilk sayfanız yüklenmeden önce tetiklenir ve sayfa manipülasyonu için tasarlanan her kod bir sayfa yenilendikten sonra yürütülür. Bu çok ince bir hata olabilir. Bazı sistemlerde iyi çalışıyor gibi görünebilir, ancak diğerlerinde düzensiz, tekrarlanması zor olan garipliğin ortaya çıkmasına neden olabilir.
Klasik jQuery sözdizimi:
$(document).ready(function() {
});
Bu sorunu çözmek için (ve bana güven bu bir sorundur) jQuery Mobile geliştiricileri sayfa etkinlikleri oluşturdu. Özetle sayfa olayları, belirli bir sayfa yürütme noktasında tetiklenen olaylardır. Bu sayfa olaylarından biri bir pageinit olayıdır ve bunu şu şekilde kullanabiliriz:
$(document).on('pageinit', function() {
});
Daha da ileri gidebilir ve belge seçici yerine bir sayfa kimliği kullanabiliriz. Diyelim ki bir kimlik endeksine sahip jQuery Mobile sayfamız var :
<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>
Yalnızca dizin sayfası tarafından kullanılabilecek kodu çalıştırmak için bu sözdizimini kullanabiliriz:
$('#index').on('pageinit', function() {
});
Sayfa her yüklenişinde ve ilk kez gösterildiğinde Pageinit olayı yürütülür. Sayfa elle yenilenmedikçe veya Ajax sayfa yüklemesi kapatılmadığı sürece tekrar tetiklenmez. Bir sayfayı her ziyaret ettiğinizde kodun yürütülmesini istiyorsanız, pagebeforeshow etkinliğini kullanmak daha iyidir .
İşte çalışan bir örnek: Bu sorunu göstermek için http://jsfiddle.net/Gajotres/Q3Usv/ .
Bu soru hakkında birkaç not daha. 1 html birden fazla sayfa veya birden fazla HTML dosyası paradigması kullanırsanız kullanın, tüm özel JavaScript sayfanızın işlenmesini tek bir ayrı JavaScript dosyasına ayırmanız önerilir. Bu, kodunuzu daha iyi hale getirecektir, ancak özellikle bir jQuery Mobile uygulaması oluştururken çok daha iyi bir kod genel görünümüne sahip olacaksınız .
Başka bir özel jQuery Mobile etkinliği de var ve buna mobileinit deniyor . Ne zaman jQuery Mobile başlar, bir tetikler mobileinit belge nesne üzerinde olay. Varsayılan ayarları geçersiz kılmak için bunları mobileinit'e bağlayın . Mobileinit kullanımına iyi bir örnek, Ajax sayfa yüklemesini kapatmak veya varsayılan Ajax yükleyici davranışını değiştirmektir.
$(document).on("mobileinit", function(){
//apply overrides here
});
Sayfa etkinlikleri geçiş sırası
İlk olarak tüm olayları burada bulabilirsiniz: http://api.jquerymobile.com/category/events/
Diyelim ki A sayfamız ve B sayfamız var, bu bir boşaltma / yükleme sırası:
sayfa B - etkinlik sayfası
sayfa B - etkinlik sayfası oluştur
B sayfası - etkinlik pageinit
sayfa A - etkinlik sayfası
sayfa A - olay çağrı etiketi
sayfa A - etkinlik sayfa gizleme
sayfa B - etkinlik sayfası
sayfa B - etkinlik sayfa gösterisi
Daha iyi sayfa etkinliklerini anlamak için şunu okuyun:
pagebeforeload
, pageload
Ve pageloadfailed
bir dış sayfa yüklendiğinde ateşlenir
pagebeforechange
, pagechange
ve pagechangefailed
sayfa değiştirme olaylarıdır. Bu olaylar, bir kullanıcı uygulamalardaki sayfalar arasında gezinirken tetiklenir.
pagebeforeshow
, pagebeforehide
, pageshow
Ve pagehide
sayfa geçiş olaylardır. Bu olaylar bir geçiş öncesinde, sırasında ve sonrasında tetiklenir ve adlandırılır.
pagebeforecreate
, pagecreate
ve pageinit
sayfa başlatma içindir.
pageremove
bir sayfa DOM'dan kaldırıldığında tetiklenebilir ve sonra işlenebilir
Sayfa yükleniyor jsFiddle örneği: http://jsfiddle.net/Gajotres/QGnft/
AJAX etkin değilse, bazı olaylar tetiklenmeyebilir.
Sayfa geçişini önle
Herhangi bir nedenle sayfa geçişinin bazı durumlarda önlenmesi gerekiyorsa, bu kodla yapılabilir:
$(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');;
}
}
});
Bu örnek her durumda işe yarayacaktır çünkü her sayfa geçişinin bir dilenmesini tetikleyecektir ve en önemlisi sayfa geçişi gerçekleşmeden önce sayfa değişikliğini önleyecektir.
İşte çalışan bir örnek:
Birden çok olay bağlama / tetiklemeyi önleme
jQuery Mobile
klasik web uygulamalarından farklı bir şekilde çalışır. Bir sayfayı her ziyaret ettiğinizde etkinliklerinizi nasıl bağlamayı başardığınıza bağlı olarak, etkinlikleri tekrar tekrar bağlar. Bu bir hata değil jQuery Mobile
, sayfalarını nasıl ele aldığıdır. Örneğin, bu kod snippet'ine bir göz atın:
$(document).on('pagebeforeshow','#index' ,function(e,data){
$(document).on('click', '#test-button',function(e) {
alert('Button click');
});
});
Çalışan jsFiddle örneği: http://jsfiddle.net/Gajotres/CCfL4/
#İndex click page sayfasını her ziyaret edişinizde # test-button düğmesine bağlanacaktır . Sayfa 1'den sayfa 2'ye ve birkaç kez geri giderek test edin. Bu sorunu önlemenin birkaç yolu vardır:
Çözüm 1
En iyi çözüm pageinit
olayları bağlamak için kullanmak olacaktır. Resmi bir belgeye bakarsanız, pageinit
SADECE bir kez tetikleneceğini göreceksiniz, tıpkı belge hazır gibi, bu yüzden olayların tekrar bağlanmasının bir yolu yoktur. Bu en iyi çözümdür, çünkü olayları off yöntemiyle kaldırırken olduğu gibi işleme yükünüz yoktur.
Çalışan jsFiddle örneği: http://jsfiddle.net/Gajotres/AAFH8/
Bu çalışma çözümü, daha önceki problemli bir örnek temelinde yapılır.
Çözüm 2
Etkinliği bağlamadan önce kaldırın:
$(document).on('pagebeforeshow', '#index', function(){
$(document).off('click', '#test-button').on('click', '#test-button',function(e) {
alert('Button click');
});
});
Çalışan jsFiddle örneği: http://jsfiddle.net/Gajotres/K8YmG/
Çözüm 3
Bunun gibi bir jQuery Filtre seçici kullanın:
$('#carousel div:Event(!click)').each(function(){
//If click is not bind to #carousel div do something
});
Etkinlik filtresi resmi jQuery çerçevesinin bir parçası olmadığından şu adreste bulunabilir: http://www.codenothing.com/archives/2009/event-filter/
Özetle, eğer hız ana endişenizse, Çözüm 2 , Çözüm 1'den çok daha iyidir.
Çözüm 4
Yeni bir tane, muhtemelen en kolayı.
$(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;
}
});
});
Çalışan jsFiddle örneği: http://jsfiddle.net/Gajotres/Yerv9/
Bu çözüm için sholsinger'a Tnx : http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/
pageChange olay tuhaflıkları - iki kez tetikleme
Bazen sayfalama olayı iki kez tetiklenebilir ve daha önce bahsedilen sorunla ilgisi yoktur.
Pagebeforechange olayının iki kez gerçekleşmesinin nedeni, toPage bir jQuery gelişmiş DOM nesnesi olmadığında changePage'deki özyinelemeli çağrıdan kaynaklanır. Geliştiricinin etkinlik içindeki toPage değerini değiştirmesine izin verildiğinden bu özyineleme tehlikelidir. Geliştirici sürekli olarak bir dizeye toPage değerini ayarlarsa, bir nesne olup olmadığına bakılmaksızın pagebeforechange olay işleyicisi içinde sonsuz bir özyinelemeli döngü oluşur. Pageload olayı yeni sayfayı veri nesnesinin page özelliği olarak geçirir (Bu, dokümantasyona eklenmelidir, şu anda listelenmemektedir). Pageload olayı bu nedenle yüklenen sayfaya erişmek için kullanılabilir.
Bu, pageChange aracılığıyla ek parametreler gönderdiğiniz için birkaç kelimeyle gerçekleşiyor.
Misal:
<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>
Bu sorunu gidermek için Sayfa olayları geçiş sırasında listelenen tüm sayfa olaylarını kullanın .
Sayfa Değiştirme Süreleri
Belirtildiği gibi, bir jQuery Mobile sayfasından diğerine geçtiğinizde, genellikle DOM'da zaten var olan başka bir jQuery Mobile sayfasına bir bağlantıyı tıklatarak veya $ .mobile.changePage'i el ile çağırarak, birkaç olay ve sonraki eylemler gerçekleşir. Üst düzeyde aşağıdaki eylemler gerçekleşir:
- Sayfa değiştirme işlemi başladı
- Yeni bir sayfa yüklendi
- Bu sayfanın içeriği "geliştirildi" (tarz)
- Mevcut sayfadan yeni sayfaya geçiş (slayt / pop / vb.)
Bu, ortalama bir sayfa geçiş ölçütüdür:
Sayfa yükleme ve işleme: 3 ms
Sayfa geliştirme: 45 ms
Geçiş: 604 ms
Toplam süre: 670 ms
* Bu değerler milisaniye cinsindendir.
Gördüğünüz gibi, bir geçiş olayı yürütme süresinin neredeyse% 90'ını yiyor.
Sayfa geçişleri arasında veri / parametre kullanımı
Sayfa geçişi sırasında bir sayfadan diğerine parametre göndermek mümkündür. Birkaç şekilde yapılabilir.
Referans: https://stackoverflow.com/a/13932240/1848600
Çözüm 1:
ChangePage ile değerler iletebilirsiniz:
$.mobile.changePage('page2.html', { dataUrl : "page2.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : true, changeHash : true });
Ve bunları şöyle okuyun:
$(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>
Çözüm 2:
Veya depolama amacıyla kalıcı bir JavaScript nesnesi oluşturabilirsiniz. Ajax sayfa yükleme için kullanıldığından (ve sayfa hiçbir şekilde yeniden yüklenmediğinden), bu nesne etkin kalacaktır.
var storeObject = {
firstname : '',
lastname : ''
}
Örnek: http://jsfiddle.net/Gajotres/9KKbx/
Çözüm 3:
Önceki sayfadaki verilere şu şekilde de erişebilirsiniz:
$(document).on('pagebeforeshow', '#index',function (e, data) {
alert(data.prevPage.attr('id'));
});
prevPage nesnesi önceki sayfanın tamamını tutar.
Çözüm 4:
Son çözüm olarak localStorage'ın şık bir HTML uygulamasına sahibiz. Yalnızca HTML5 tarayıcılarla (Android ve iOS tarayıcılar dahil) çalışır, ancak depolanan tüm veriler sayfa yenileme sırasında kalıcıdır.
if(typeof(Storage)!=="undefined") {
localStorage.firstname="Dragan";
localStorage.lastname="Gaic";
}
Örnek: http://jsfiddle.net/Gajotres/J9NTr/
Muhtemelen en iyi çözüm, ancak iOS 5.X'in bazı sürümlerinde başarısız olacaktır. İyi bilinen bir hatadır.
.live()
/ .bind()
/ Kullanma.delegate()
Bahsetmeyi unuttum (ve hatırlatmak için tnx andleer ) olay bağlama / bağlama, canlı / ölme ve bağlama / çözme için açma / kapama kullanımdan kaldırıldı.
JQuery'nin .live () yöntemi, 1.3 sürümünde API'ye tanıtıldığında bir nimet olarak görülüyordu. Tipik bir jQuery uygulamasında çok fazla DOM manipülasyonu olabilir ve elemanlar gelip giderken kanca ve kancayı çıkarmak çok sıkıcı olabilir. .live()
Yöntem mümkün olan selektör dayalı uygulamanın ömrü boyunca bir etkinlik kanca yaptı. Harika değil mi? Yanlış, .live()
yöntem son derece yavaş. .live()
Yöntem aslında belge nesnesi etkinliklerini, kanca olan araçlarının bu belge ulaşana kadar etkinliği oluşturulan bu elementten olay şart kabarcık. Bu inanılmaz derecede zaman alıcı olabilir.
Artık kullanımdan kaldırıldı. JQuery ekibindeki insanlar artık kullanılmasını önermiyor ve ben de bunu yapmıyor. Olayları kancalamak ve kancalarını çıkarmak sıkıcı olsa da, kodunuz .live()
yöntem olmadan ondan çok daha hızlı olacaktır .
Bunun yerine .live()
kullanmalısınız .on()
. .live () '.on()
den yaklaşık 2-3 kat daha hızlıdır . Bu etkinliğe bağlanma ölçütüne bir göz atın: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , her şey oradan netleşecek.
Kıyaslama:
JQuery Mobile sayfa etkinlikleri karşılaştırması için yapılmış mükemmel bir komut dosyası var . Burada bulunabilir: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Ancak onunla herhangi bir şey yapmadan önce alert
bildirim sistemini kaldırmanızı öneririm (her "sayfayı değiştir" uygulamayı durdurarak bu verileri size gösterecek) ve console.log
işlevini değiştirecek .
Temel olarak bu komut dosyası tüm sayfa etkinliklerinizi günlüğe kaydeder ve bu makaleyi dikkatlice okursanız (sayfa olayları açıklamaları) jQm'nin sayfa geliştirmeleri, sayfa geçişleri için ne kadar zaman harcadığını bileceksiniz ....
Son notlar
Her zaman, ve her zaman resmi jQuery Mobile belgelerini okuyun . Genellikle size gerekli bilgileri sağlar ve diğer bazı belgelerin aksine bu, yeterince açıklama ve kod örnekleri ile oldukça iyidir.
değişiklikler:
- 30.01.2013 - Yeni bir çoklu olay tetikleme yöntemi eklendi
- 31.01.2013 - Sayfa geçişleri arasındaki Veri / Parametreler manipülasyonu bölümü için daha iyi bir açıklama eklendi
- 03.02.2013 - Sayfa geçişleri arasında Veri / Parametreler manipülasyonu bölümüne yeni içerik / örnekler eklendi
- 22.05.2013 - Sayfa geçişi / değişiklik önleme için bir çözüm eklendi ve resmi sayfa etkinlikleri API dokümanlarına bağlantılar eklendi
- 18.05.2013 - Çoklu olay bağlamaya karşı başka bir çözüm eklendi