[javascript] jQuery Mobile : 문서 준비 및 페이지 이벤트

jQuery Mobile을 사용하고 있으며 기존 문서 준비와 jQuery Mobile 페이지 이벤트의 차이점을 이해하는 데 어려움이 있습니다.

  1. 실제 차이점은 무엇입니까?

    왜해야

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

    보다 낫다

    $(document).on('pageinit') {
    
    });
  2. 한 페이지에서 다른 페이지로 전환 할 때 페이지 이벤트 순서는 무엇입니까?

  3. 한 페이지에서 다른 페이지로 데이터를 보내려면 어떻게해야하며 이전 페이지에서 데이터에 액세스 할 수 있습니까?



답변

jQuery Mobile 1.4 업데이트 :

내 원본 기사는 오래된 페이지 처리 방식, 기본적으로 jQuery Mobile 1.4 이전의 모든 내용을 다루었습니다. 이전 처리 방법은 이제 더 이상 사용되지 않으며 jQuery Mobile 1.5까지 (포함)까지 계속 유지되므로 적어도 내년과 jQuery Mobile 1.6까지 아래 언급 된 모든 것을 계속 사용할 수 있습니다.

pageinit를 포함한 오래된 이벤트 는 더 이상 존재하지 않으며 pagecontainer 위젯 으로 대체됩니다 . Pageinit 가 완전히 지워지고 대신 pagecreate 를 사용할 수 있습니다 . 해당 이벤트는 동일하게 유지되며 변경되지 않습니다.

새로운 페이지 이벤트 처리 방법에 관심이있는 경우 여기를 살펴보십시오 . 다른 경우에는이 기사를 계속 진행하십시오. jQuery Mobile 1.4 +를 사용하는 경우 에도이 답변을 읽어보십시오. 페이지 이벤트를 넘어서서 유용한 정보를 많이 찾을 수 있습니다.

오래된 내용 :

이 문서는 또한 내 블로그의 일환으로 볼 수 있습니다 여기에 .

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

jQuery 에서 가장 먼저 배우는 것은 $(document).ready()함수 내에서 코드를 호출 하여 DOM이로드되는 즉시 모든 것이 실행되도록하는 것입니다. 그러나 jQuery Mobile 에서 Ajax는 탐색 할 때 각 페이지의 컨텐츠를 DOM으로로드하는 데 사용됩니다. 이 때문에 $(document).ready()첫 번째 페이지가로드되기 전에 트리거되고 페이지 조작을위한 모든 코드가 페이지를 새로 고친 후에 실행됩니다. 이것은 매우 미묘한 버그 일 수 있습니다. 일부 시스템에서는 제대로 작동하는 것처럼 보일 수 있지만 다른 시스템에서는 불규칙하고 반복하기 이상한 반복이 발생할 수 있습니다.

클래식 jQuery 구문 :

$(document).ready(function() {

});

이 문제를 해결하기 위해 (그리고 이것이 문제라고 믿어) jQuery Mobile 개발자가 페이지 이벤트를 작성했습니다. 간단히 말해서 페이지 이벤트는 특정 페이지 실행 시점에서 트리거되는 이벤트입니다. 이러한 페이지 이벤트 중 하나는 pageinit 이벤트이며 다음과 같이 사용할 수 있습니다.

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

});

더 나아가서 문서 선택기 대신 페이지 ID를 사용할 수 있습니다. ID 인덱스 가있는 jQuery Mobile 페이지가 있다고 가정 해 보겠습니다 .

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

인덱스 페이지에서만 사용할 수있는 코드를 실행하려면 다음 구문을 사용할 수 있습니다.

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

});

Pageinit 이벤트는 페이지가로드되고 처음으로 표시 될 때마다 실행됩니다. 페이지를 수동으로 새로 고치거나 Ajax 페이지로드를 끄지 않으면 다시 트리거되지 않습니다. 페이지를 방문 할 때마다 코드를 실행하려면 pagebeforeshow 이벤트 를 사용하는 것이 좋습니다 .

다음은 실제 예입니다. http://jsfiddle.net/Gajotres/Q3Usv/ 이 문제를 보여줍니다.

이 질문에 대한 더 많은 메모가 없습니다. 1 html 여러 페이지 또는 여러 HTML 파일 패러다임을 사용하더라도 모든 사용자 정의 JavaScript 페이지 처리를 하나의 개별 JavaScript 파일로 분리하는 것이 좋습니다. 이것은 코드를 더 좋게 만들지 만 특히 jQuery Mobile 응용 프로그램 을 만드는 동안 코드 개요가 훨씬 좋습니다 .

또 다른 특별한 jQuery Mobile 이벤트가 있으며 mobileinit 라고 합니다 . jQuery Mobile이 시작 되면 문서 객체에서 mobileinit 이벤트를 트리거 합니다. 기본 설정을 대체하려면 설정을 mobileinit에 바인드 하십시오 . mobileinit 사용법 의 좋은 예 중 하나는 Ajax 페이지로드를 끄거나 기본 Ajax 로더 동작을 변경하는 것입니다.

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

페이지 이벤트 전환 순서

먼저 모든 이벤트를 여기에서 찾을 수 있습니다 : http://api.jquerymobile.com/category/events/

페이지 A와 페이지 B가 있다고 가정하면 언로드 /로드 순서입니다.

  1. 페이지 B – 이벤트 pagebeforecreate

  2. 페이지 B-이벤트 페이지 작성

  3. 페이지 B-이벤트 페이지 초기화

  4. 페이지 A- 숨기기 이벤트 페이지

  5. 페이지 A-이벤트 페이지 제거

  6. 페이지 A-이벤트 페이지 숨기기

  7. 페이지 B – 이벤트 pagebeforeshow

  8. 페이지 B-이벤트 페이지

더 나은 페이지 이벤트를 이해하려면 다음을 읽으십시오.

  • pagebeforeload, pageloadpageloadfailed외부 페이지가로드 될 때 해고
  • pagebeforechange, pagechangepagechangefailed페이지 변경 이벤트입니다. 이 이벤트는 사용자가 응용 프로그램의 페이지를 탐색 할 때 시작됩니다.
  • pagebeforeshow, pagebeforehide, pageshowpagehide페이지 전환 이벤트입니다. 이러한 이벤트는 전환 전, 도중 및 후에 발생하며 이름이 지정됩니다.
  • pagebeforecreate, pagecreatepageinit페이지 초기화됩니다.
  • pageremove DOM에서 페이지를 제거하면 시작된 다음 처리 될 수 있음

페이지 로딩 jsFiddle 예제 : http://jsfiddle.net/Gajotres/QGnft/

AJAX를 사용하지 않으면 일부 이벤트가 시작되지 않을 수 있습니다.

페이지 전환 방지

어떤 이유로 인해 페이지 전환을 어떤 조건에서 방지해야하는 경우이 코드를 사용하여 수행 할 수 있습니다.

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

이 예제는 모든 페이지 전환을 요청하면 트리거되며 페이지 전환이 발생하기 전에 페이지 변경을 방지하는 가장 중요한 사항이기 때문에 어떤 경우에도 작동합니다.

다음은 실제 예입니다.

여러 이벤트 바인딩 / 트리거 방지

jQuery Mobile클래식 웹 애플리케이션과 다른 방식으로 작동합니다. 일부 페이지를 방문 할 때마다 이벤트를 바인드 한 방법에 따라 계속해서 이벤트가 바인드됩니다. 이것은 오류가 아니며 단순히 jQuery Mobile페이지를 처리 하는 방법 입니다. 예를 들어,이 코드 스 니펫을 살펴보십시오.

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

작동하는 jsFiddle 예제 : http://jsfiddle.net/Gajotres/CCfL4/

#index 클릭 이벤트 페이지를 방문 할 때마다 버튼 # test-button에 바인딩됩니다 . 1 페이지에서 2 페이지로 이동 한 후 여러 번 뒤로 이동하여 테스트하십시오. 이 문제를 방지 할 수있는 몇 가지 방법이 있습니다.

해결책 1

최상의 솔루션은 pageinit이벤트를 바인딩하는 데 사용 하는 것 입니다. 공식 문서를 살펴보면 pageinit문서 준비와 마찬가지로 한 번만 트리거 되는 것을 알 수 있으므로 이벤트가 다시 바인딩 될 방법이 없습니다. 메소드를 사용하지 않고 이벤트를 제거 할 때와 같이 처리 오버 헤드가 없기 때문에이 방법이 가장 좋습니다.

작동하는 jsFiddle 예제 : http://jsfiddle.net/Gajotres/AAFH8/

이 작업 솔루션은 이전의 문제가 발생한 예를 기반으로 만들어졌습니다.

해결책 2

바인드하기 전에 이벤트를 제거하십시오.

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

작동하는 jsFiddle 예제 : http://jsfiddle.net/Gajotres/K8YmG/

해결책 3

다음과 같이 jQuery 필터 선택기를 사용하십시오.

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

이벤트 필터는 공식 jQuery 프레임 워크의 일부가 아니므로 http://www.codenothing.com/archives/2009/event-filter/ 에서 찾을 수 있습니다 .

요컨대, 속도가 주요 관심사이면 솔루션 2 가 솔루션 1보다 훨씬 낫습니다.

해결책 4

새로운 것, 아마도 가장 쉬운 것입니다.

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

작동하는 jsFiddle 예제 : http://jsfiddle.net/Gajotres/Yerv9/

이 솔루션 을 위해 Sholsinger 에게 보내는 Tnx : http://sholsinger.com/archive/2011/08/prevent-jquery-live-handlers-from-firing-multiple-times/

pageChange 이벤트 문제-두 번 트리거

때로는 pagechange 이벤트가 두 번 트리거 될 수 있으며 앞에서 언급 한 문제와 관련이 없습니다.

pagebeforechange 이벤트가 두 번 발생하는 이유는 toPage가 jQuery 확장 DOM 객체가 아닌 경우 changePage의 재귀 호출 때문입니다. 이 재귀는 개발자가 이벤트 내에서 toPage를 변경할 수 있으므로 위험합니다. 개발자가 객체에 관계없이 무한 재귀 루프가 발생하는지 여부에 관계없이 pagebeforechange 이벤트 핸들러 내에서 지속적으로 toPage를 문자열로 설정하는 경우. pageload 이벤트는 새 페이지를 데이터 객체의 page 속성으로 전달합니다 (이는 문서에 추가되어 현재 나열되어 있지 않음). 따라서 pageload 이벤트를 사용하여로드 된 페이지에 액세스 할 수 있습니다.

한마디로 이것은 pageChange를 통해 추가 매개 변수를 전송하기 때문에 발생합니다.

예:

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

이 문제를 해결하려면 페이지 이벤트 전환 순서에 나열된 페이지 이벤트를 사용하십시오 .

페이지 변경 시간

언급 한 바와 같이, 일반적으로 DOM에 이미 존재하는 다른 jQuery Mobile 페이지에 대한 링크를 클릭하거나 $ .mobile.changePage를 수동으로 호출하여 하나의 jQuery Mobile 페이지에서 다른 jQuery Mobile 페이지로 변경하면 몇 가지 이벤트 및 후속 조치가 발생합니다. 높은 수준에서 다음과 같은 동작이 발생합니다.

  • 페이지 변경 프로세스가 시작되었습니다
  • 새 페이지가로드되었습니다
  • 해당 페이지의 내용은 “향상된”(스타일)
  • 기존 페이지에서 새 페이지로 전환 (슬라이드 / 팝 / 등)

이것은 평균 페이지 전환 벤치 마크입니다.

페이지로드 및 처리 : 3ms

페이지 향상 : 45ms

전환 : 604ms

총 시간 : 670ms

*이 값은 밀리 초입니다.

보시다시피 전환 이벤트는 거의 90 %의 실행 시간을 소비하고 있습니다.

페이지 전환 사이의 데이터 / 파라미터 조작

페이지 전환 중에 한 페이지에서 다른 페이지로 매개 변수를 보낼 수 있습니다. 몇 가지 방법으로 수행 할 수 있습니다.

참조 : https://stackoverflow.com/a/13932240/1848600

해결책 1 :

changePage로 값을 전달할 수 있습니다.

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

그리고 이것을 다음과 같이 읽으십시오.

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

해결책 2 :

또는 저장 목적으로 영구 JavaScript 객체를 생성 할 수 있습니다. 긴 Ajax가 페이지로드에 사용되고 (페이지가 어떤 식으로도 다시로드되지 않음) 해당 객체는 활성 상태를 유지합니다.

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

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

해결책 3 :

다음과 같이 이전 페이지의 데이터에 액세스 할 수도 있습니다.

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

prevPage 객체는 완전한 이전 페이지를 보유합니다.

해결책 4 :

마지막 솔루션으로 localStorage의 멋진 HTML 구현이 있습니다. HTML5 브라우저 (Android 및 iOS 브라우저 포함)에서만 작동하지만 저장된 모든 데이터는 페이지 새로 고침을 통해 지속됩니다.

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

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

아마도 최선의 해결책이지만 일부 버전의 iOS 5.X에서는 실패합니다. 잘 알려진 오류입니다.

사용하지 마십시오 .live()/ .bind()/.delegate()

이벤트 바인딩 / 바인딩, 라이브 / 다이 및 바인드 / 바인드 해제에 on / off 사용 을 언급하는 것을 잊었습니다 (그리고 tnx andleer ).

jQuery의 .live () 메소드는 1.3 버전의 API에 도입되었을 때 신의 선물로 여겨졌습니다. 일반적인 jQuery 앱에는 많은 DOM 조작이있을 수 있으며 요소가 오거나 갈 때 연결을 끊는 것이 매우 지루해질 수 있습니다. 이 .live()방법을 통해 선택기를 기반으로 앱 수명 동안 이벤트를 연결할 수있었습니다. 그렇죠? 잘못된 .live()방법은 매우 느립니다. 이 .live()메서드는 실제로 이벤트를 문서 객체에 연결합니다. 즉, 이벤트가 문서에 도달 할 때까지 이벤트를 생성 한 요소에서 이벤트가 버블 링되어야합니다. 놀랍게도 시간이 많이 걸릴 수 있습니다.

더 이상 사용되지 않습니다. jQuery 팀의 사람들은 더 이상 사용을 권장하지 않으며 나도 권장하지 않습니다. 이벤트를 연결하거나 해제하는 것이 지루할 수 있지만 코드를 사용하는 것보다 .live()방법이 없으면 코드가 훨씬 빠릅니다 .

대신 .live()을 사용해야합니다 .on(). .live ().on() 보다 약 2-3 배 빠릅니다 . 이 이벤트 바인딩 벤치 마크를 살펴보십시오 : http://jsperf.com/jquery-live-vs-delegate-vs-on/34 , 거기에서 모든 것이 명확해질 것입니다.

벤치마킹 :

jQuery Mobile 페이지 이벤트 벤치마킹을 위한 훌륭한 스크립트가 있습니다. https://github.com/jquery/jquery-mobile/blob/master/tools/page-change-time.js 에서 찾을 수 있습니다 . 그러나 당신이 그것으로 무엇이든하기 전에 나는 alert알림 시스템 을 제거하고 (각 “변경 페이지”는 응용 프로그램을 중지 하여이 데이터를 보여줄 것입니다) console.log기능을 변경하는 것이 좋습니다.

기본적 으로이 스크립트는 모든 페이지 이벤트를 기록 하며이 기사를주의 깊게 읽으면 (페이지 이벤트 설명) jQm이 페이지 향상, 페이지 전환에 소비 한 시간을 알 수 있습니다 ….

최종 노트

항상, 저는 항상 공식 jQuery Mobile 문서를 읽습니다 . 일반적으로 필요한 정보를 제공하며 다른 문서와 달리 설명과 코드 예제가 충분하여 다소 유용합니다.

변경 사항 :

  • 30.01.2013-여러 이벤트 트리거링 방지의 새로운 방법 추가
  • 31.01.2013- 페이지 전환 사이의 데이터 / 매개 변수 조작 장에 대한보다 명확한 설명이 추가되었습니다.
  • 03.02.2013- 페이지 전환 사이의 데이터 / 매개 변수 조작 장에 새로운 내용 / 예제 추가
  • 22.05.2013-페이지 전환 / 변경 방지 솔루션 추가 및 공식 페이지 이벤트 API 문서에 대한 링크 추가
  • 18.05.2013-다중 이벤트 바인딩에 대한 다른 솔루션 추가

답변

여러분 중 일부는 이것이 유용하다고 생각할 것입니다. 페이지에 붙여 넣기 만하면 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');});

페이지가 언로드 될 때 (페이지에서 멀어 질 때) 실행되므로 콘솔에서 언로드가 표시되지 않습니다. 다음과 같이 사용하십시오.

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

그리고 당신은 내가 무슨 뜻인지 알 수 있습니다.


답변

이것은 올바른 방법입니다.

인덱스 페이지에서만 사용할 수있는 코드를 실행하려면 다음 구문을 사용할 수 있습니다.

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


답변

jQuery-mobile에서 문서 준비와 페이지 이벤트의 간단한 차이점은 다음과 같습니다.

  1. 문서 준비 이벤트는 전체 HTML 페이지에 사용됩니다.

    $(document).ready(function(e) {
        // Your code
    });
  2. 페이지 이벤트가있는 경우 특정 페이지 이벤트를 처리하는 데 사용하십시오.

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

pageinit 이벤트를 처리하기 위해 문서를 사용할 수도 있습니다.

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

});


답변

.on ()을 사용하는 동안 기본적으로 사용중인 라이브 쿼리입니다.

반면에 .ready (귀하의 경우)는 정적 쿼리입니다. 데이터를 사용하는 동안 데이터를 동적으로 업데이트 할 수 있으며 페이지가로드 될 때까지 기다릴 필요가 없습니다. 특정 값을 입력 할 때 값을 데이터베이스로 전달할 수 있습니다 (필요한 경우).

실시간 검색어는 데이터 (계정 또는 게시물 또는 댓글)를 입력하는 형식에서 일반적입니다.


답변