Jquery Mobile: document ready vs. page events

estou a usar o jQuery Mobile, e estou a ter dificuldade em compreender as diferenças entre os eventos clássicos do document ready e do jQuery Mobile page.

  1. Qual é a verdadeira diferença?

    porque é que

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

    ser melhor que

    $(document).on('pageinit') {
    
    });
    
  2. Qual é a ordem dos eventos da página, quando você transita de uma página para outra?

  3. Como posso enviar dados de uma página para outra e é possível acessar dados de anteriores page?

Author: Peter Mortensen, 2013-01-23

5 answers

JQuery Mobile 1.4 Update:

O meu artigo original destinava-se ao tratamento de páginas antigas, basicamente tudo antes da jQuery Mobile 1.4. A antiga maneira de lidar com isso está agora desactualizada e vai permanecer ativa até (incluindo) jQuery Mobile 1.5, então você ainda pode usar tudo o que foi mencionado abaixo, pelo menos até o próximo ano e jQuery Mobile 1.6.

Eventos antigos, incluindo pageinit já não existem, são substituídos por pagecontainer widget. Pageinit é completamente apagado e você pode usar pagecreate em vez disso, esse evento permaneceu o mesmo e não vai ser alterado.

Se você está interessado em uma nova maneira de lidar com eventos de página dê uma olhada toma., em qualquer outro caso, sinta-se livre para continuar com este artigo. Você deve ler esta resposta mesmo se você estiver usando jQuery Mobile 1.4 +, ele vai além de eventos de página, então você provavelmente vai encontrar um monte de informações úteis.

Mais velho conteúdo:

Este artigo também pode ser encontrado como parte do meu blog toma..

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

A primeira coisa que se aprende em jQuery é chamar código dentro do $(document).ready() função para que tudo seja executado assim que o DOM for carregado. No entanto, emjQuery Mobile , Ajax é usado para carregar o conteúdo de cada página no DOM à medida que você navega. Por causa disto.$(document).ready() irá despoletar antes da sua primeira página é carregado e todos os códigos destinados à manipulação de páginas serão executados após uma actualização de páginas. Isto pode ser um insecto muito subtil. Em alguns sistemas pode parecer que funciona bem, mas em outros pode causar errática, difícil de repetir estranheza a ocorrer.

Sintaxe clássica do jQuery:

$(document).ready(function() {

});

Para resolver este problema (e acreditem que este é um problema) os programadores jQuery Mobile criaram eventos de página. Em poucas palavras eventos de página são eventos desencadeados em um ponto particular da página execucao. Um desses eventos de página é um evento pageinit e podemos usá - lo assim:

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

});

Podemos ir ainda mais longe e usar um ID de página em vez do selector de documentos. Digamos que temos uma página móvel jQuery com um índice de id ([58]}:

<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 executar um código que só estará disponível na página de índice, poderíamos usar esta sintaxe:

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

});

O evento Pageinit será executado sempre que a página estiver prestes a ser carregada e apresentada pela primeira vez. Ele não irá despoletar novamente a menos que a página seja atualizada manualmente ou o carregamento de páginas Ajax esteja desligado. No caso de querer executar o código sempre que visita uma página, é melhor usar o evento pagebefore howow .

Aqui está um exemplo de trabalho: http://jsfiddle.net/Gajotres/Q3Usv para demonstrar este problema. Mais algumas notas sobre esta questão. Não importa se você está usando 1 html várias páginas ou múltiplos arquivos HTML paradigma é aconselhável separar todos os seus personalizados JavaScript page handling into a single separate JavaScript file. Esta nota tornará o seu código ainda melhor, mas você terá uma visão geral do Código muito melhor, especialmente ao criar uma aplicação jQuery Mobile.

Há também outro evento especial jQuery Mobilee chama-se mobileinit. Quando jQuery Mobile começa, despoleta um mobileinit no objecto do documento. Para sobrepor as opções predefinidas, ligue-as a mobileinit . Um dos bons exemplos de mobileinit uso é desligar o carregamento de páginas Ajax,ou alterar o comportamento padrão do carregador Ajax.

$(document).on("mobileinit", function(){
  //apply overrides here
});
([135]}página Eventos ordem de transição Em primeiro lugar, todos os eventos podem ser encontrados aqui: http://api.jquerymobile.com/category/events/ Digamos que temos uma página a e uma página B, Isto é uma ordem de descarga / carga.
  1. Página B-evento pagebeforecreate

  2. Página B - evento pagecreate

  3. Página B - evento pageinit

  4. Página do evento pagebeforehide

  5. Página do evento pageremove

  6. Página do evento pagehide

  7. Página B-evento pagebefore how

  8. Página B - evento pageshow

Para uma melhor compreensão de eventos de página Leia isto:

  • pagebeforeload, pageload e pageloadfailed são disparados quando uma página externa é carregado
  • pagebeforechange, pagechange e pagechangefailed são eventos de alteração. Estes eventos são disparados quando um usuário está navegando entre páginas em aplicacao.
  • pagebeforeshow, pagebeforehide, pageshow e pagehide são de transição de página eventos. Estes eventos são disparados antes, durante e depois de uma transição e são nomeados.
  • pagebeforecreate, pagecreate e pageinit são para inicialização de páginas.
  • pageremove pode ser disparada e depois manuseada quando uma página é removida do DOM

Page loading jsFiddle example: http://jsfiddle.net/Gajotres/QGnft/

Se o AJAX não estiver activo, alguns acontecimentos podem não disparar.

Impedir a transição da página

Se, por alguma razão, a transição da página precisar de ser evitada, sob alguma condição, pode ser feita com 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 exemplo vai funcionar em qualquer caso, porque ele vai desencadear uma mendicidade de cada transição de página e o que é mais importante ele vai impedir a mudança de página antes de a transição de página pode ocorrer.

Aqui está um exemplo de trabalho:

Impedir a ligação/activação de eventos múltiplos

jQuery Mobile funciona de uma forma diferente das aplicações web clássicas. Dependendo de como você conseguiu vincular seus eventos cada vez que você visita alguma página, ela irá vincular eventos vezes sem conta. Isto não é um erro, é simplesmente como jQuery Mobile trata das suas páginas. Por exemplo, dê uma olhada neste excerto de código:

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

A trabalhar no exemplo jsFiddle: http://jsfiddle.net/Gajotres/CCfL4/

Cada vez que visitar a Página #index o evento click irá estar ligado ao botão #test-button. Teste-O movendo-se da página 1 para a Página 2 e para trás várias vezes. Existem poucas maneiras de prevenir este problema:

Solução 1

A melhor solução seria usar pageinit para ligar os acontecimentos. Se você der uma olhada em uma documentação oficial você vai descobrir que pageinit só irá despoletar uma vez, tal como o documento está pronto, para que os acontecimentos não voltem a ser ligados. Esta é a melhor solução porque você não tem processamento acima como ao remover eventos com o método off.

Exemplo jsFiddle: http://jsfiddle.net/Gajotres/AAFH8/

Esta solução de trabalho é feita com base num exemplo problemático anterior.

Solução 2

Remover o evento antes de o ligar:

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

A trabalhar no exemplo jsFiddle: http://jsfiddle.net/Gajotres/K8YmG/

Solução 3

Use um selector de filtro jQuery, como este:

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

Como o filtro de eventos não faz parte da estrutura oficial do jQuery, pode ser encontrado aqui: http://www.codenothing.com/archives/2009/event-filter/

Em poucas palavras, se a velocidade é a sua principal preocupação então a solução 2 é muito melhor do que a solução 1.

Solução 4

Um novo, provavelmente o mais fácil deles. todo.
$(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;
        }
    });
});
Exemplo jsFiddle: http://jsfiddle.net/Gajotres/Yerv9/

Tnx para o sholsinger para esta solução: http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

Pagechange event quirks-trigging twice

Às vezes o evento pagechange pode desencadear duas vezes e não tem nada a ver com o problema mencionado antes.

A razão o evento pagebeforechange ocorre duas vezes é devido à chamada recursiva em changePage quando toPage não é um objeto DOM aprimorado jQuery. Esta recursão é perigosa, já que o desenvolvedor pode alterar a topagem dentro do evento. Se o desenvolvedor configura consistentemente toPage para uma string, dentro do pagebeforechange event handler, independentemente de ser ou não um objeto um loop recursivo infinito irá resultar. O evento pageload passa a nova página como propriedade da página do objeto de dados (isto deve ser adicionado à documentação, não está listado atualmente). O evento pageload pode, portanto, ser usado para acessar a página carregada.

Em poucas palavras, Isto está acontecendo porque você está enviando parâmetros adicionais através de pageChange.

Exemplo:

<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 corrigir este problema, use qualquer evento de página listado em ordem de transição de eventos de Página .

Tempos De Mudança De Página

Como mencionado, quando você muda de uma página móvel jQuery para outra, tipicamente, clicando em um link para outra página móvel jQuery que já existe no DOM, ou chamando manualmente $.movel.changePage, vários eventos e ações subsequentes ocorrem. A um nível elevado, ocorrem as seguintes acções:
  • inicia-se um processo de mudança de Página
  • é carregada uma nova Página
  • o conteúdo dessa página é "melhorado" (estilizado)
  • uma transição (slide/pop/etc) da Página existente para a nova página ocorre

Esta é uma referência média de transição de páginas:

Carga e processamento de páginas: 3 ms

Page enhance: 45 ms

Transição: 604 ms

Tempo Total: 670 ms

* estes valores estão em milisegundos.

Como podem ver, um evento de transição consome quase 90% do tempo de execução.

Manipulação de dados/Parâmetros entre as transições de páginas

É possível. para enviar um parâmetro/s de uma página para outra durante a transição da página. Pode ser feito de poucas maneiras.

Referência: https://stackoverflow.com/a/13932240/1848600

Solução 1:

Pode passar valores com changePage:

$.mobile.changePage('page2.html', { dataUrl : "page2.html?paremeter=123", data : { 'paremeter' : '123' }, reloadPage : true, changeHash : true });
E lê-os como isto:
$(document).on('pagebeforeshow', "#index", function (event, data) {
    var parameters = $(this).data("url").split("?")[1];;
    parameter = parameters.replace("parameter=","");
    alert(parameter);
});

Exemplo:

Índice.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>

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

Solução 2:

Ou você pode criar um objeto JavaScript persistente para um propósito de armazenamento. Enquanto o Ajax for usado para o carregamento de páginas (e a página não for recarregada de forma alguma) esse objeto permanecerá ativo.

var storeObject = {
    firstname : '',
    lastname : ''
}
Exemplo: http://jsfiddle.net/Gajotres/9KKbx/

Solução 3:

Você também pode acessar os dados da página anterior assim:

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

PrevPage o objecto contém uma página anterior completa.

Solução 4:

Como última solução, temos uma implementação Nifty HTML do localStorage. Ele só funciona com navegadores HTML5 (incluindo navegadores Android e iOS), mas todos os dados armazenados são persistentes através da página actualizar.

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

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

Provavelmente a melhor solução, mas falhará em algumas versões do iOS 5.X. É um erro bem conhecido.

Não uses .live() / .bind() / .delegate()

Esqueci-me de mencionar (e tnx andleer para me lembrar) uso on/off para ligação de eventos/unbinding, live/die E bind/unbind são depreciados.

O .o método vivo de jQuery foi visto como uma dádiva de Deus quando foi introduzido a a API na versão 1.3. Em um app jQuery típico pode haver um monte de manipulação DOM e pode se tornar muito tedioso para gancho e desapertar à medida que os elementos vêm e vão. O método .live() tornou possível ligar um evento para a vida útil da aplicação com base no seu selector. Óptimo, não é? Errado, o método é extremamente lento. O método .live() realmente liga os seus eventos ao objecto do documento, o que significa que o evento deve fazer uma bolha a partir do elemento que gerou o evento até atingir o documento. Isto pode ser incrivelmente demorado.

Agora está desacreditado. As pessoas da equipa jQuery já não recomendam o seu uso e eu também não.mesmo que possa ser entediante para enganchar e desatar eventos, o seu código será muito mais rápido sem o método .live() do que com ele.

Em vez de .live() deve utilizar .on(). .on() é cerca de 2-3x mais rápido que .live(). Dê uma olhada neste evento benchmark binding benchmark: http://jsperf.com/jquery-live-vs-delegate-vs-on/34 tudo ficará claro a partir daí.

Avaliação comparativa: [136]} Há um excelente script feito para o jQuery Mobile.benchmarking de eventos de página. Ela pode ser encontrada aqui: https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js. Mas antes de fazer qualquer coisa com ele, eu aconselho você a remover sua alert sistema de notificação (cada "página de alteração de" vai mostrar de dados interrompendo a aplicação) e alterando-a para console.log função.

Basicamente, este programa irá registar todos os seus eventos de página e, se ler este artigo com cuidado (descrição dos eventos de página), irá saber quanto tempo o jQm passou com as melhorias de página, As transições de página ....

Notas finais

Sempre, e quero dizer sempre ler a documentação oficial jQuery Mobile. Ele geralmente irá fornecer-lhe informações necessárias, e ao contrário de alguma outra documentação este é bastante bom, com explicações suficientes e exemplos de código.

Alterações:

  • 30.01.2013-acrescentou um novo método de prevenção de múltiplos eventos
  • 31.01.2013-adicionou uma melhor clarificação para o capítulo manipulação de dados / Parâmetros entre as transições de páginas
  • 03.02.2013-adicionou novos conteúdos / exemplos ao capítulo manipulação de dados / Parâmetros entre as transições de páginas
  • 22.05.2013-adicionou uma solução para page transition / change prevention and added links to the official page events API documentation
  • 18.05.2013-adicionou outra solução contra a ligação de eventos múltiplos
 436
Author: Gajotres, 2017-09-10 20:43:14
Alguns de vocês podem achar isto útil. Basta copiar colá-lo para a sua página e obterá uma sequência em que os eventos são disparados na consola 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');});

Você não vai ver a descarga na consola, pois esta é disparada quando a página está sendo descarregada (quando você se afasta da página). Use-o assim:

$(window).unload(function () { debugger; console.log("window unloaded");});
E vais ver o que quero dizer.
 17
Author: Matas Vaitkevicius, 2017-09-10 20:49:32

Esta é a maneira correcta:

Para executar um código que só estará disponível na página de índice, poderíamos usar esta sintaxe:

$(document).on('pageinit', "#index",  function() {
    ...
});
 3
Author: kecco, 2017-09-10 20:46:09

A diferença simples entre o evento document ready e page in jQuery-mobile é que:

  1. O evento document ready é usado para toda a página HTML,

    $(document).ready(function(e) {
        // Your code
    });
    
  2. Quando existe um evento de Página, usar para lidar com um evento de página em particular:

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

Também pode usar o documento para lidar com o evento pageinit:

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

});
 1
Author: LeoMobDev, 2017-09-10 20:48:22

Enquanto usa .on (), é basicamente uma consulta ao vivo que você está usando.

Por outro lado,pronto (como no seu caso) é uma consulta estática. Ao usá-lo, você pode atualizar dados dinamicamente e não tem que esperar pela página para carregar. Você pode simplesmente passar os valores em seu banco de dados (se necessário) quando um determinado valor é inserido.

O uso de consultas ao vivo é comum em formulários onde introduzimos dados (conta ou posts ou mesmo Comentários).

 -1
Author: Pranjal, 2017-09-10 20:50:36