javascript phonegap - jQuery Mobile:documento preparado vs.eventos de página




demos online (5)

Estoy usando jQuery Mobile y tengo problemas para entender las diferencias entre los documentos clásicos preparados y los eventos de jQuery Mobile.

  1. ¿Cuál es la diferencia real?

    Porque deberia

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

    ser mejor que

    $(document).on('pageinit') {
    
    });
    
  2. ¿Cuál es el orden de los eventos de la página, cuando hace la transición de una página a otra?

  3. ¿Cómo puedo enviar datos de una página a otra y es posible acceder a los datos de la página anterior?


Answers

Esta es la forma correcta:

Para ejecutar código que solo estará disponible para la página de índice, podríamos usar esta sintaxis:

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

Mientras usas .on (), es básicamente una consulta en vivo que estás usando.

Por otro lado, .ready (como en su caso) es una consulta estática. Mientras lo usa, puede actualizar los datos dinámicamente y no tiene que esperar a que se cargue la página. Simplemente puede pasar los valores a su base de datos (si es necesario) cuando se ingresa un valor particular.

El uso de consultas en vivo es común en formularios donde ingresamos datos (cuenta o publicaciones o incluso comentarios).


Actualización de jQuery Mobile 1.4:

Mi artículo original estaba destinado a la forma antigua de manejo de páginas, básicamente todo antes de jQuery Mobile 1.4. La antigua forma de manejo ahora está en desuso y permanecerá activa hasta (incluyendo) jQuery Mobile 1.5, por lo que aún puede usar todo lo que se menciona a continuación, al menos hasta el próximo año y jQuery Mobile 1.6.

Los eventos antiguos, incluido pageinit ya no existen, se reemplazan con el widget pagecontainer . Pageinit se borra completamente y puede usar pagecreate en su lugar, ese evento se mantuvo igual y no se cambiará.

Si está interesado en una nueva forma de manejar los eventos de la página, eche un vistazo here , en cualquier otro caso, no dude en continuar con este artículo. Debería leer esta respuesta, incluso si está utilizando jQuery Mobile 1.4 +, va más allá de los eventos de la página, por lo que probablemente encontrará mucha información útil.

Contenido anterior:

Este artículo también se puede encontrar como parte de mi blog HERE .

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

Lo primero que aprendes en jQuery es llamar al código dentro de la función $(document).ready() para que todo se ejecute tan pronto como se cargue el DOM. Sin embargo, en jQuery Mobile , Ajax se utiliza para cargar el contenido de cada página en el DOM mientras navega. Debido a esto, $(document).ready() se activará antes de que se cargue la primera página y todos los códigos destinados a la manipulación de la página se ejecutarán después de una actualización de la página. Esto puede ser un error muy sutil. En algunos sistemas puede parecer que funciona bien, pero en otros puede hacer que se produzcan situaciones erráticas y difíciles de repetir.

Sintaxis clásica de jQuery:

$(document).ready(function() {

});

Para resolver este problema (y créeme, este es un problema) los desarrolladores de jQuery Mobile crearon eventos de página. En pocas palabras, los eventos son eventos desencadenados en un punto particular de ejecución de la página. Uno de esos eventos de página es un evento de pageinit y podemos usarlo así:

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

});

Podemos ir aún más lejos y usar una identificación de página en lugar del selector de documentos. Digamos que tenemos la página de jQuery Mobile con un índice de identificación:

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

Para ejecutar código que solo estará disponible para la página de índice, podríamos usar esta sintaxis:

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

});

El evento Pageinit se ejecutará cada vez que la página se cargue y se muestre por primera vez. No se activará de nuevo a menos que la página se actualice manualmente o que la carga de la página Ajax esté desactivada. En caso de que desee que el código se ejecute cada vez que visite una página, es mejor usar el evento pagebeforeshow .

Aquí hay un ejemplo http://jsfiddle.net/Gajotres/Q3Usv/ : http://jsfiddle.net/Gajotres/Q3Usv/ para demostrar este problema.

Algunas notas más sobre esta pregunta. No importa si está utilizando el paradigma de varias páginas HTML o múltiples archivos HTML, se recomienda separar todo el manejo de su página JavaScript personalizada en un solo archivo JavaScript separado. Esto hará que su código sea mejor, pero tendrá una mejor descripción del código, especialmente al crear una aplicación jQuery Mobile .

También hay otro evento especial de jQuery Mobile y se llama mobileinit . Cuando se inicia jQuery Mobile , activa un evento mobileinit en el objeto de documento. Para anular la configuración predeterminada, conéctelos a mobileinit . Uno de los buenos ejemplos de uso de Mobileinit es desactivar la carga de páginas Ajax o cambiar el comportamiento predeterminado del cargador Ajax.

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

Página eventos orden de transición

Primero, todos los eventos se pueden encontrar aquí: http://api.jquerymobile.com/category/events/

Digamos que tenemos una página A y una página B, este es un orden de descarga / carga:

  1. página B - evento pagebeforecreate

  2. página B - evento pagecreate

  3. página B - página de evento

  4. página A - página del evento antes de pagebeforehide

  5. página A - evento pageremove

  6. página A - página de evento

  7. página B - evento pagebeforeshow

  8. página B - página de eventos

Para comprender mejor los eventos de la página, lea esto:

  • pagebeforeload , pageload y pageloadfailed se pageloadfailed cuando se carga una página externa
  • pagebeforechange , pagechange y pagechangefailed son eventos de cambio de página. Estos eventos se activan cuando un usuario navega entre las páginas de las aplicaciones.
  • pagebeforeshow , pagebeforehide , pageshow y pagehide son eventos de transición de página. Estos eventos se activan antes, durante y después de una transición y se denominan.
  • pagebeforecreate , pagecreate y pageinit son para la inicialización de páginas.
  • pageremove puede pageremove y luego manejarse cuando se elimina una página del DOM

Página cargando ejemplo de jsFiddle: http://jsfiddle.net/Gajotres/QGnft/

Si AJAX no está habilitado, es posible que algunos eventos no se activen.

Prevenir la transición de la página

Si, por algún motivo, se debe evitar la transición de la página en alguna condición, se puede hacer con este código:

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

Este ejemplo funcionará en cualquier caso porque se activará al comienzo de cada transición de página y, lo que es más importante, evitará el cambio de página antes de que se produzca la transición de página.

Aquí hay un ejemplo de trabajo:

Prevenir múltiples eventos de enlace / activación

jQuery Mobile funciona de una manera diferente a las aplicaciones web clásicas. Dependiendo de cómo haya logrado vincular sus eventos cada vez que visite alguna página, los eventos se vincularán una y otra vez. Esto no es un error, es simplemente la forma en que jQuery Mobile maneja sus páginas. Por ejemplo, eche un vistazo a este fragmento de código:

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

Ejemplo de jsFiddle en funcionamiento: http://jsfiddle.net/Gajotres/CCfL4/

Cada vez que visite la página # el evento de clic de índice estará vinculado al botón # test-button . Pruébelo pasando de la página 1 a la página 2 y retrocediendo varias veces. Hay algunas formas de prevenir este problema:

Solución 1

La mejor solución sería utilizar pageinit para enlazar eventos. Si echa un vistazo a la documentación oficial, descubrirá que pageinit se activará SOLAMENTE una vez, al igual que el documento listo, por lo que no hay forma de que los eventos se pageinit a pageinit . Esta es la mejor solución porque no tiene una sobrecarga de procesamiento como cuando se eliminan eventos con el método off.

Ejemplo de jsFiddle en funcionamiento: http://jsfiddle.net/Gajotres/AAFH8/

Esta solución de trabajo se realiza sobre la base de un ejemplo problemático anterior.

Solucion 2

Elimina el evento antes de enlazarlo:

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

Ejemplo de jsFiddle en funcionamiento: http://jsfiddle.net/Gajotres/K8YmG/

Solucion 3

Use un selector de filtro jQuery, como este:

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

Como el filtro de eventos no forma parte del marco oficial de jQuery, se puede encontrar aquí: http://www.codenothing.com/archives/2009/event-filter/

En pocas palabras, si la velocidad es su principal preocupación, entonces la Solución 2 es mucho mejor que la Solución 1.

Solucion 4

Una nueva, probablemente la más fácil de todas.

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

Ejemplo de jsFiddle en funcionamiento: http://jsfiddle.net/Gajotres/Yerv9/

Diríjase al sholsinger por esta solución: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

Cambios de evento de pageChange - disparando dos veces

A veces, el evento pagechange puede activarse dos veces y no tiene nada que ver con el problema mencionado anteriormente.

La razón por la que el evento pagebeforechange ocurre dos veces se debe a la llamada recursiva en changePage cuando toPage no es un objeto DOM mejorado de jQuery. Esta recursión es peligrosa, ya que el desarrollador puede cambiar la toPage dentro del evento. Si el desarrollador establece sistemáticamente toPage a una cadena, dentro del controlador de eventos pagebeforechange, independientemente de si se trata de un objeto o no, se generará un bucle recursivo infinito. El evento de carga de páginas pasa a la nueva página como la propiedad de la página del objeto de datos (esto debe agregarse a la documentación, no se encuentra en la lista actualmente). Por lo tanto, el evento de carga de página podría utilizarse para acceder a la página cargada.

En pocas palabras, esto sucede porque está enviando parámetros adicionales a través de pageChange.

Ejemplo:

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

Para solucionar este problema, use cualquier evento de página listado en Orden de transición de eventos de página .

Tiempos de cambio de página

Como se mencionó, cuando se cambia de una página de jQuery Mobile, por lo general, ya sea haciendo clic en un enlace a otra página de jQuery Mobile que ya existe en el DOM, o llamando manualmente a $ .mobile.changePage, se producen varios eventos y acciones posteriores. En un nivel alto se producen las siguientes acciones:

  • Se inicia un proceso de cambio de página.
  • Se carga una nueva página.
  • El contenido de esa página está "mejorado" (con estilo)
  • Se produce una transición (slide / pop / etc) desde la página existente a la nueva página

Este es un punto de referencia de transición de página promedio:

Página de carga y procesamiento: 3 ms

Mejora de página: 45 ms.

Transición: 604 ms

Tiempo total: 670 ms

* Estos valores están en milisegundos.

Entonces, como puede ver, un evento de transición consume casi el 90% del tiempo de ejecución.

Manipulación de datos / parámetros entre transiciones de página.

Es posible enviar un / s parámetro / s de una página a otra durante la transición de la página. Se puede hacer de varias maneras.

Referencia: https://.com/a/13932240/1848600

Solución 1:

Puedes pasar valores con changePage:

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

Y léelos así:

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

Solución 2:

O puede crear un objeto JavaScript persistente para un propósito de almacenamiento. Mientras se utilice Ajax para cargar la página (y la página no se vuelva a cargar de ninguna manera), el objeto permanecerá activo.

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

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

Solución 3:

También puede acceder a los datos de la página anterior de esta manera:

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

prevPage objeto contiene una página anterior completa.

Solución 4:

Como última solución tenemos una implementación HTML ingeniosa de localStorage. Solo funciona con navegadores HTML5 (incluidos los navegadores Android y iOS) pero todos los datos almacenados son persistentes a través de la actualización de la página.

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

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

Probablemente la mejor solución, pero fallará en algunas versiones de iOS 5.X. Es un error bien conocido.

No utilice .live() / .bind() / .delegate()

Olvidé mencionar (y tnx andleer para recordarme) el uso de activación / desactivación para la vinculación / desvinculación de eventos, vivir / morir y vincular / desvincular están en desuso.

El método .live () de jQuery fue visto como una bendición cuando se introdujo en la API en la versión 1.3. En una aplicación jQuery típica, puede haber una gran cantidad de manipulación de DOM y puede ser muy tedioso enganchar y desenganchar a medida que los elementos van y vienen. El método .live() hizo posible conectar un evento durante la vida de la aplicación en función de su selector. Gran derecho Incorrecto, el método .live() es extremadamente lento. El método .live() realidad enlaza sus eventos al objeto de documento, lo que significa que el evento debe aumentar desde el elemento que generó el evento hasta que llega al documento. Esto puede ser increíblemente lento.

Ahora está en desuso. La gente del equipo de jQuery ya no recomienda su uso y yo tampoco. A pesar de que puede ser tedioso enganchar y desenganchar eventos, su código será mucho más rápido sin el método .live() que con él.

En lugar de .live() debes usar .on() . .on() es aproximadamente 2-3x más rápido que .live () . Eche un vistazo a este evento de enlace de referencia: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , todo estará claro a partir de ahí.

Benchmarking:

Hay un excelente script hecho para la evaluación de eventos de la página de jQuery Mobile . Se puede encontrar aquí: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js . Pero antes de hacer algo con él, le aconsejo que elimine su sistema de notificación de alert (cada "página de cambio" le mostrará estos datos deteniendo la aplicación) y la cambiará a la función console.log .

Básicamente, esta secuencia de comandos registrará todos los eventos de su página y si lee este artículo detenidamente (descripciones de los eventos de la página) sabrá cuánto tiempo ha dedicado jQm las mejoras de la página, las transiciones de la página ...

Notas finales

Siempre, y me refiero a leer siempre la documentación oficial de jQuery Mobile . Por lo general, le proporcionará la información necesaria y, a diferencia de otra documentación, esta es bastante buena, con suficientes explicaciones y ejemplos de código.

Cambios:

  • 30.01.2013 - Se agregó un nuevo método de prevención de activación de eventos múltiples
  • 31.01.2013 - Se agregó una mejor aclaración para la manipulación de datos / parámetros del capítulo entre las transiciones de página
  • 03.02.2013 - Se agregaron nuevos contenidos / ejemplos al capítulo Datos / Parámetros de manipulación entre transiciones de página
  • 22.05.2013 - Se agregó una solución para la transición de página / prevención de cambios y se agregaron enlaces a la página oficial de documentación de la API
  • 18.05.2013 - Se agregó otra solución contra el enlace de eventos múltiples

Algunos de ustedes pueden encontrar esto útil. Simplemente copie, péguelo en su página y obtendrá una secuencia en la que se activan los eventos en la consola de Chrome ( Ctrl + Shift + I ).

$(document).on('pagebeforecreate',function(){console.log('pagebeforecreate');});
$(document).on('pagecreate',function(){console.log('pagecreate');});
$(document).on('pageinit',function(){console.log('pageinit');});
$(document).on('pagebeforehide',function(){console.log('pagebeforehide');});
$(document).on('pagebeforeshow',function(){console.log('pagebeforeshow');});
$(document).on('pageremove',function(){console.log('pageremove');});
$(document).on('pageshow',function(){console.log('pageshow');});
$(document).on('pagehide',function(){console.log('pagehide');});
$(window).load(function () {console.log("window loaded");});
$(window).unload(function () {console.log("window unloaded");});
$(function () {console.log('document ready');});

No vas a ver la descarga en la consola, ya que se activa cuando la página se descarga (cuando te alejas de la página). Úsalo así:

$(window).unload(function () { debugger; console.log("window unloaded");});

Y verás lo que quiero decir.


Una cosa más que proporciona el nodo es la capacidad de crear múltiples instancias v8 de nodo utilizando el proceso hijo del nodo ( childProcess.fork() cada uno de los cuales requiere 10 MB de memoria según los documentos) sobre la marcha, por lo que no afecta al proceso principal que ejecuta el servidor. Por lo tanto, la descarga de un trabajo en segundo plano que requiere una gran carga del servidor se convierte en un juego de niños y podemos matarlos fácilmente cuando sea necesario.

He estado usando mucho los nodos y en la mayoría de las aplicaciones que creamos, requieren conexiones de servidor al mismo tiempo, por lo tanto, un gran tráfico de red. Frameworks como Express.js y los nuevos Koajs (que eliminaron el infierno de devolución de llamada) han hecho que trabajar en nodo sea aún más fácil.





javascript jquery html5 jquery-mobile cordova