javascript - soutien - mondial 2026 maroc




jQuery Mobile: les documents prêts et les événements de page (4)

J'utilise jQuery Mobile et j'ai de la difficulté à comprendre les différences entre les événements de page classiques prêts pour le document et ceux de jQuery Mobile.

  1. Quelle est la vraie différence?

    Pourquoi devrais-je

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

    être meilleur que

    $(document).on('pageinit') {
    
    });
    
  2. Quel est l'ordre des événements de la page, lorsque vous passez d'une page à une autre?

  3. Comment puis-je envoyer des données d'une page à une autre et est-il possible d'accéder aux données de la page précédente?


Mise à jour de jQuery Mobile 1.4:

Mon article original était destiné à l'ancienne façon de gérer les pages, essentiellement tout ce qui existait avant jQuery Mobile 1.4. L'ancien mode de gestion est maintenant obsolète et il restera actif jusqu'à (y compris) jQuery Mobile 1.5, de sorte que vous pouvez toujours utiliser tout ce qui est mentionné ci-dessous, au moins jusqu'à l'année prochaine et jQuery Mobile 1.6.

Les anciens événements, y compris pageinit n'existent plus, ils sont remplacés par le widget pagecontainer . Pageinit est effacé complètement et vous pouvez utiliser pagecreate à la place, cet événement est resté le même et il ne va pas être changé.

Si vous êtes intéressé par une nouvelle façon de gérer les événements de page, jetez un oeil here , dans tous les autres cas, n'hésitez pas à continuer avec cet article. Vous devriez lire cette réponse même si vous utilisez jQuery Mobile 1.4 +, cela va au-delà des événements de page, donc vous trouverez probablement beaucoup d'informations utiles.

Contenu plus ancien:

Cet article peut également être trouvé dans le cadre de mon blog HERE .

$(document).on('pageinit') vs $(document).ready()

La première chose que vous apprenez dans jQuery est d'appeler du code dans la fonction $(document).ready() afin que tout soit exécuté dès que le DOM est chargé. Cependant, dans jQuery Mobile , Ajax est utilisé pour charger le contenu de chaque page dans le DOM lorsque vous naviguez. À cause de cela $(document).ready() se déclenchera avant que votre première page soit chargée et chaque code destiné à la manipulation de page sera exécuté après une actualisation de page. Cela peut être un bug très subtil. Sur certains systèmes, il peut sembler que cela fonctionne bien, mais sur d'autres, cela peut provoquer une bizarrerie erratique, difficile à répéter.

La syntaxe jQuery classique:

$(document).ready(function() {

});

Pour résoudre ce problème (et croyez-moi c'est un problème), les développeurs jQuery Mobile ont créé des événements de page. En un mot, les événements de page sont des événements déclenchés à un point particulier de l'exécution de la page. Un de ces événements de page est un événement pageinit et nous pouvons l'utiliser comme ceci:

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

});

Nous pouvons aller encore plus loin et utiliser un identifiant de page au lieu du sélecteur de document. Disons que nous avons une page jQuery Mobile avec un index 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>

Pour exécuter du code qui ne sera disponible que sur la page d'index, nous pouvons utiliser cette syntaxe:

$('#index').on('pageinit', function() {

});

L' événement Pageinit sera exécuté chaque fois que la page sera chargée et affichée pour la première fois. Il ne se déclenchera plus à moins que la page ne soit rafraîchie manuellement ou que le chargement de la page Ajax soit désactivé. Dans le cas où vous voulez que le code s'exécute chaque fois que vous visitez une page, il est préférable d'utiliser l'événement pagebeforeshow .

Voici un exemple de travail: http://jsfiddle.net/Gajotres/Q3Usv/ pour montrer ce problème.

Quelques notes de plus sur cette question. Peu importe si vous utilisez 1 pages HTML ou plusieurs pages HTML, il est conseillé de séparer toute la gestion de vos pages JavaScript en un seul fichier JavaScript séparé. Cela notera rendre votre code meilleur mais vous aurez une meilleure vue d'ensemble du code, en particulier lors de la création d'une application jQuery Mobile .

Il existe également un autre événement jQuery Mobile spécial, appelé mobileinit . Lorsque jQuery Mobile démarre, il déclenche un événement mobileinit sur l'objet document. Pour remplacer les paramètres par défaut, associez-les à mobileinit . Un bon exemple d'utilisation de mobileinit consiste à désactiver le chargement de la page Ajax ou à modifier le comportement du chargeur Ajax par défaut.

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

Ordre de transition des événements de page

Tout d'abord tous les événements peuvent être trouvés ici: http://api.jquerymobile.com/category/events/

Disons que nous avons une page A et une page B, ceci est un ordre de déchargement / chargement:

  1. page B - événement pagebeforecreate

  2. page B - événement pagecreate

  3. page B - événement api.jquerymobile.com/pageinit

  4. page A - page de l'événementavant la pagebeforehide

  5. page A - événement pageremove

  6. page A - page pagehide événement

  7. page B - événement pagebeforeshow

  8. page B - page de l'événement

Pour mieux comprendre les événements de la page, lisez ceci:

  • pagebeforeload , pageload et pageloadfailed sont déclenchés lorsqu'une page externe est chargée
  • pagebeforechange , pagechange et pagechangefailed sont des événements de changement de page. Ces événements sont déclenchés lorsqu'un utilisateur navigue entre les pages des applications.
  • pagebeforeshow , pagebeforehide , pageshow et pagehide sont des événements de transition de page. Ces événements sont déclenchés avant, pendant et après une transition et sont nommés.
  • pagebeforecreate , pagecreate et pageinit sont pour l'initialisation de la page.
  • pageremove peut être déclenché puis géré lorsqu'une page est supprimée du DOM

Chargement de la page Exemple jsFiddle: http://jsfiddle.net/Gajotres/QGnft/

Si AJAX n'est pas activé, certains événements peuvent ne pas se déclencher.

Empêcher la transition de page

Si, pour une raison quelconque, la transition de page doit être empêchée à certaines conditions, cela peut être fait avec ce code:

$(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');;
        }
    }
});

Cet exemple fonctionnera dans tous les cas car il se déclenchera à la demande de chaque transition de page et ce qui est le plus important empêchera le changement de page avant que la transition de page puisse avoir lieu.

Voici un exemple de travail:

Empêcher la liaison / le déclenchement d'événements multiples

jQuery Mobile fonctionne différemment des applications Web classiques. En fonction de la façon dont vous avez réussi à lier vos événements chaque fois que vous visitez une page, elle liera les événements encore et encore. Ce n'est pas une erreur, c'est simplement comment jQuery Mobile gère ses pages. Par exemple, jetez un oeil à cet extrait de code:

$(document).on('pagebeforeshow','#index' ,function(e,data){
    $(document).on('click', '#test-button',function(e) {
        alert('Button click');
    });
});

Exemple de travail de jsFiddle: http://jsfiddle.net/Gajotres/CCfL4/

Chaque fois que vous visitez la page #index, l' événement click va être lié au bouton # test-button . Testez-le en passant de la page 1 à la page 2 et revenez plusieurs fois. Il existe quelques moyens d'éviter ce problème:

Solution 1

La meilleure solution serait d'utiliser pageinit pour lier les événements. Si vous jetez un œil à une documentation officielle, vous découvrirez que pageinit ne se déclenchera qu'une seule fois, tout comme le document est prêt, donc il n'y a aucun moyen de pageinit événements. C'est la meilleure solution car vous n'avez pas de surcharge de traitement comme lors de la suppression d'événements avec la méthode off.

Exemple de travail de jsFiddle: http://jsfiddle.net/Gajotres/AAFH8/

Cette solution de travail est faite sur la base d'un exemple problématique précédent.

Solution 2

Supprimer l'événement avant de le lier:

$(document).on('pagebeforeshow', '#index', function(){
    $(document).off('click', '#test-button').on('click', '#test-button',function(e) {
        alert('Button click');
    });
});

Exemple de travail jsFiddle: http://jsfiddle.net/Gajotres/K8YmG/

Solution 3

Utilisez un sélecteur de filtre jQuery, comme ceci:

$('#carousel div:Event(!click)').each(function(){
    //If click is not bind to #carousel div do something
});

Comme le filtre d'événements ne fait pas partie du framework officiel jQuery, il peut être trouvé ici: http://www.codenothing.com/archives/2009/event-filter/

En un mot, si la vitesse est votre principale préoccupation, la Solution 2 est bien meilleure que la Solution 1.

Solution 4

Un nouveau, probablement le plus facile de tous.

$(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;
        }
    });
});

Exemple de travail jsFiddle: http://jsfiddle.net/Gajotres/Yerv9/

Tnx à la sholsinger pour cette solution: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

pageChanger les caprices des événements - déclencher deux fois

Parfois, l'événement pagechange peut déclencher deux fois et cela n'a rien à voir avec le problème mentionné précédemment.

La raison pour laquelle l'événement pagebeforechange se produit deux fois est due à l'appel récursif dans changePage lorsque toPage n'est pas un objet DOM amélioré jQuery. Cette récursivité est dangereuse, car le développeur est autorisé à changer le toPage dans l'événement. Si le développeur définit systématiquement toPage sur une chaîne, dans le gestionnaire d'événements pagebeforechange, qu'il s'agisse ou non d'un objet, une boucle récursive infinie sera générée. L'événement pageload passe la nouvelle page en tant que propriété de page de l'objet de données (ceci doit être ajouté à la documentation, il n'est pas listé actuellement). L'événement pageload pourrait donc être utilisé pour accéder à la page chargée.

En quelques mots, cela se passe parce que vous envoyez des paramètres supplémentaires via pageChange.

Exemple:

<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>

Pour résoudre ce problème, utilisez n'importe quel événement de page répertorié dans l' ordre de transition des événements de page .

Changement de page fois

Comme mentionné précédemment, lorsque vous passez d'une page jQuery Mobile à une autre, généralement en cliquant sur un lien vers une autre page jQuery Mobile déjà existante dans le DOM ou en appelant manuellement $ .mobile.changePage, plusieurs événements et actions subséquentes se produisent. À un niveau élevé, les actions suivantes se produisent:

  • Un processus de changement de page est commencé
  • Une nouvelle page est chargée
  • Le contenu de cette page est "amélioré" (style)
  • Une transition (slide / pop / etc) de la page existante à la nouvelle page se produit

Ceci est un benchmark de transition de page moyenne:

Chargement de la page et traitement: 3 ms

Amélioration de la page: 45 ms

Transition: 604 ms

Durée totale: 670 ms

* Ces valeurs sont en millisecondes.

Comme vous pouvez le voir, un événement de transition consomme près de 90% du temps d'exécution.

Manipulation de données / paramètres entre les transitions de page

Il est possible d'envoyer un ou plusieurs paramètres d'une page à une autre pendant la transition de page. Cela peut être fait de plusieurs façons.

Référence: https://.com/a/13932240/1848600

Solution 1:

Vous pouvez passer des valeurs avec changePage:

$.mobile.changePage('page2.html', { dataUrl : "page2.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : true, changeHash : true });

Et lisez-les comme ceci:

$(document).on('pagebeforeshow', "#index", function (event, data) {
    var parameters = $(this).data("url").split("?")[1];;
    parameter = parameters.replace("parameter=","");
    alert(parameter);
});

Example :

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>

Solution 2:

Ou vous pouvez créer un objet JavaScript persistant à des fins de stockage. Comme Ajax est utilisé pour le chargement de la page (et que la page n'est pas rechargée), cet objet reste actif.

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

Exemple: http://jsfiddle.net/Gajotres/9KKbx/

Solution 3:

Vous pouvez également accéder aux données de la page précédente comme ceci:

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

L' objet prevPage contient une page précédente complète.

Solution 4:

Comme une dernière solution, nous avons une implémentation HTML astucieuse de localStorage. Il fonctionne uniquement avec les navigateurs HTML5 (y compris les navigateurs Android et iOS), mais toutes les données stockées sont persistantes via l'actualisation de la page.

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

Exemple: http://jsfiddle.net/Gajotres/J9NTr/

Probablement la meilleure solution mais elle échouera dans certaines versions d'iOS 5.X. C'est une erreur bien connue.

N'utilisez pas .live() / .bind() / .delegate()

J'ai oublié de mentionner (et tnx andleer pour me le rappeler) utiliser on / off pour la liaison / déconnexion d'événements, live / die et bind / unbind sont obsolètes.

La méthode .live () de jQuery a été considérée comme une aubaine quand elle a été introduite dans l'API en version 1.3. Dans une application jQuery typique, il peut y avoir beaucoup de manipulation DOM et il peut devenir très fastidieux d'accrocher et de décrocher au fur et à mesure que les éléments vont et viennent. La méthode .live() a permis d'accrocher un événement pour la vie de l'application en fonction de son sélecteur. Très bien? .live() , la méthode .live() est extrêmement lente. La méthode .live() ses événements à l'objet document, ce qui signifie que l'événement doit surgir de l'élément qui a généré l'événement jusqu'à ce qu'il atteigne le document. Cela peut prendre énormément de temps.

Il est maintenant obsolète. Les gens de l'équipe de jQuery ne recommandent plus son utilisation et moi non plus. Même si cela peut être fastidieux de décrocher et de décrocher des événements, votre code sera beaucoup plus rapide sans la méthode .live() qu'avec celle-ci.

Au lieu de .live() vous devriez utiliser .on() . .on() est environ 2-3x plus rapide que .live () . Jetez un oeil à cet événement de référence contraignant: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , tout sera clair à partir de là.

Benchmarking:

Il y a un excellent script pour l'analyse comparative des événements de la page jQuery Mobile . Il peut être trouvé ici: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Mais avant de faire quoi que ce soit, je vous conseille de supprimer son système de notification d' alert (chaque "page de changement" va vous montrer ces données en arrêtant l'application) et le changer en console.log fonction.

Fondamentalement, ce script enregistrera tous vos événements de page et si vous lisez attentivement cet article (descriptions d'événements de page), vous saurez combien de temps jQm passé des améliorations de page, des transitions de page ....

Notes finales

Toujours, et je veux dire toujours lire la documentation officielle de jQuery Mobile . Il vous fournira généralement les informations nécessaires, et contrairement à d'autres documents, celui-ci est plutôt bon, avec suffisamment d'explications et d'exemples de code.

Changements:

  • 30.01.2013 - Ajout d'une nouvelle méthode de prévention des événements multiples
  • 31.01.2013 - Ajout d'une meilleure clarification pour le chapitre Manipulation de données / paramètres entre les transitions de page
  • 03.02.2013 - Ajout de nouveaux contenus / exemples au chapitre Manipulation de données / paramètres entre les transitions de page
  • 22.05.2013 - Ajout d'une solution pour la transition de pages / prévention des changements et ajout de liens vers la documentation officielle de l'API des événements de page
  • 18.05.2013 - Ajout d'une autre solution contre la liaison d'événements multiples

C'est la bonne façon:

Pour exécuter du code qui ne sera disponible que pour la page d'index, nous pourrions utiliser cette syntaxe:

$(document).on('pageinit', "#index",  function() {
    ...
});

La simple différence entre un document prêt et un événement de page dans jQuery-mobile est la suivante:

  1. L'événement document ready est utilisé pour toute la page HTML,

    $(document).ready(function(e) {
        // Your code
    });
    
  2. Lorsqu'il y a un événement de page, utilisez pour gérer un événement de page particulier:

    <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-->
    

Vous pouvez également utiliser un document pour gérer l'événement pageinit:

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

});

Lorsque vous utilisez .on (), il s'agit essentiellement d'une requête en direct que vous utilisez.

D'un autre côté, .ready (comme dans votre cas) est une requête statique. En l'utilisant, vous pouvez mettre à jour dynamiquement les données et ne pas avoir à attendre le chargement de la page. Vous pouvez simplement transmettre les valeurs dans votre base de données (si nécessaire) lorsqu'une valeur particulière est saisie.

L'utilisation de requêtes en direct est courante dans les formulaires où nous saisissons des données (compte ou messages ou même commentaires).





cordova