Подтвердить что ты не робот

Как я могу отложить переход страницы в jQuery Mobile до тех пор, пока данные страницы не будут готовы?

У меня есть мобильное одностраничное веб-приложение, которое построено с использованием jquery-mobile (jqm) и нокаута. Само приложение имеет несколько страниц, но все они содержатся в одном документе HTML.

Проблема: после изменения моей модели создания модели для страницы от синхронизации до асинхронного поведения у меня возникла проблема с тем, что jquery-mobile запускает свои события до того, как данные будут готовы.

Предыстория: до недавнего времени я работал с образцами данных, в основном огромным блоком JSON, и все работало плавно. С новым асинхронным составом моделей просмотра из разных источников данные не готовы немедленно, и мой метод "buildViewModel" выполняет обратный вызов продолжения вместо просто синхронного возвращения данных.

Я подписываюсь на события pagebeforecreate и pagebeforechange и запускаю код, чтобы заполнить здесь viewmodel. Проблема в том, что после возвращения из обработчика события jqm запускает оставшуюся цепочку событий до того, как данные будут доступны. Это приводит к переходу страницы на неподготовленную страницу, что нежелательно.

Я попытался вызвать event.preventDefault во всех предшествующих событиях и вручную вызывать $.mobile.changePage, когда страница готова быть a) улучшена, и b) переход страницы произойдет, но без везения.

Я сканировал источник jquery-mobile, но не смог обнаружить ничего похожего на то, что это позволило бы мне отложить событие pagebeforeshow, что по сути является тем, что мне нужно, чтобы иметь возможность правильно отображать страницу.

Как я могу гарантировать, что 1) данные доступны, и 2) нокаут был применен для выполнения начальных манипуляций с DOM, прежде чем jquery-mobile попытается улучшить страницу и до того, как она выполнит переход на страницу?

Я также рассмотрел возможность использования синхронного ajax для извлечения ресурсов, но это (я думаю) не работает для ресурсов, загруженных с устройства (используя PhoneGap/Cordova), и имеет другие негативные последствия, которых я бы хотел избежать.

FWIW, я бы хотел, чтобы избежать необходимости вручную обрабатывать все события навигации, проводя вверх по всем обработчикам кликов, но при необходимости я открыт для всех решений.

Извините, если это дубликат; Я искал и читал массу вопросов, но не нашел ответа или вопроса, который был совершенно таким же. Мне просто кажется невероятным, что я первым ударил бы по этой проблеме, так как я считаю, что это распространенный сценарий.

Обновление: пояснение описания сценария проблемы.

4b9b3361

Ответ 1

У меня была такая же проблема.

Единственное решение, с которым я смог придумать, - написать настраиваемый обработчик перехода, который откладывает начало перехода до запроса Ajax завершается.

Здесь fiddle, показывающий технику. Скрипка не использует нокаут, но показывает, как отложить переход.

В принципе, поскольку $.ajax() возвращает обещание, я могу передать это в обещание, возвращенное обработчиком перехода по умолчанию, и вернуть его из моего нового обработчика.

В моем обработчике pagebeforeshow я прикладываю к Ajax обещание на странице, чтобы обработчик перехода имел к нему доступ. Не уверен, что это лучший способ, но мне понравилось это лучше, чем использование глобальной переменной.

Единственное, что мне не понравилось в этом, это то, что он задерживает начало перехода до тех пор, пока не поступит ответ Ajax, так что может показаться, что страница "повесила" пользователя, чтобы он снова щелкнул. Вручную показ сообщения о загрузке заставляет чувствовать себя немного более отзывчивым.

Надеюсь, что это поможет, и, пожалуйста, дайте мне знать, если вы найдете лучшее решение!

Ответ 2

Отсрочка перехода на новую страницу до готовности ее содержимого является очень распространенной проблемой при обращении к динамическому контенту в jQuery Mobile. Наиболее удобные способы решения этой проблемы:

  • Вместо классической навигации типа href создайте ссылки на действия "click", которые сначала извлекут контент, построят новую страницу в DOM и затем начнут переход на эту новую страницу через $.mobile.changePage. Преимущество такого подхода состоит в том, что его легко установить, недостатком является то, что вы не перемещаетесь с классическими ссылками href

  • Привязать событие pagebeforechange на уровне документа, чтобы определить, является ли целевая страница вашей навигационной страницей на странице, содержащей динамический контент. В таком случае вы можете запретить навигацию по умолчанию, не тратьте время на создание страницы и переход на успех. Это описано в документах JQM для динамически вставляемого контента. Преимущество состоит в том, что вы все еще можете полагаться на стандартную навигацию по ссылкам href, но для исправления и навигации по страницам требуется немного больше кода и дизайна вверх.

    $(document).on( "pagebeforechange", function( e, data ) {
        if ( typeof data.toPage === "string" ) {
             if ( data.toPage === "myDynamicPageName" ) {
                 e.preventDefault(); //used to stop transition to the page (for now)
    
                 /*
                    Here you can make your ajax call
                    In you callback, once you have generated the page you can call
                    $.mobile.changePage
                    (you can pass the Div of the new page instead of its name as
                    the changepage parameter to avoid interrupting again the page change) 
                 */
              }
          }
    });
    

Ответ 3

Установите ссылку, чтобы вызвать функцию загрузки, вместо перехода на страницу. В вашей функции загрузки отобразите "загрузочное сообщение" и выполните вызов JSON. Наконец, в функции обратного вызова JSON измените страницу на страницу2

функция загрузки

function loadPage2() {
    /* show wait page */
    $.mobile.loading( 'show', {
            text: 'Loading massively huge dataset',
            textVisible: true
    });

     /* perform JSON call then call callback */
 }

Функция обратного вызова

function callback() {
    $.mobile.changePage("#page2");
}

Вот рабочий JSFiddle: http://jsfiddle.net/8w7PM/

Обратите внимание, что если вы не хотите, чтобы пользователи могли обновлять поля ввода в Page 1 во время ожидания, введите "страницу ожидания" между страницами 1 и 2, при этом инициализация "страницы ожидания" выполняется так же, как "loadPage2".

Ответ 4

Думаю, вам нужно снова запустить для всего виджета, который вы хотите связать с ответом на

Например, вам нужно будет вызывать trigger с событием create или refrest для элемента $("#element").trigger('create'); JQuery Mobile свяжет все события по умолчанию с элементом, поскольку он

--- EDIT ---

Я только что создал образец кода, я думаю, что это же ваша проблема, попробуйте ссылку http://jsfiddle.net/ndkhoiits/BneqW/embedded/result/

Прежде чем разбить данные, мы должны вызвать для обслуживания, чтобы получить их для отображения, поэтому все события, привязанные jqm, будут удалены.

У меня есть обходное решение для этого, не делайте jqm fire что-либо в элементе, мы будем запускать его после того, как все данные привязаны к knockoutjs Попробуйте исправленную версию http://jsfiddle.net/ndkhoiits/c5a2b/embedded/result/

Это код http://jsfiddle.net/ndkhoiits/c5a2b/

Ответ 5

У меня есть небольшое приложение jQuery для мобильных устройств /KnockoutJS, и я столкнулся с той же проблемой. Мое приложение содержит около 5 страниц. Все они содержатся в одном физическом документе HTML со стандартной разметкой <div data-role="page">, разделяющей отдельные страницы.

В результате успеха $.ajax я, наконец, пошел с навигацией на основе кликов и пожара $.mobile.changePage().

Одним из недостатков этого метода является то, что вы потеряете подсветку своей кнопки, полагаясь на атрибуты onclick vs href. См. Мой связанный пост: href vs переходы между страницами и подсветка кнопок

Позже я решил поставить оба и полагаться на href, чтобы выполнить навигацию, используя onclick, чтобы вызвать мою логику JavaScript для загрузки ViewModels и т.д. Единственное место, где я обнаружил, что это проблема, - это когда возможно подтверждение на исходной странице. Если это не удается, переход уже начался, и пользовательский интерфейс снова начнет мигать на исходной странице. Ужасно, но это происходит только в ограниченном экземпляре в моем приложении.

Я не думаю, что это относится к Knockout. Мое точное решение может представить вам проблемы в том, что ваша навигация, вероятно, будет завершена до полной загрузки вашей модели, но если вы полагаетесь на $.mobile.changePage(), все должно работать и скрывать вашу страницу до ее загрузки. Переходы должны работать нормально.

<a href="#MyNewPage" data-bind="click:LoadNewPage" data-role="button">
    Load Page
</a>

$.ajax({
    url: url,
    cache: false,
    dataType: "json",
    data: requestData,
    type: "POST",
    async: true,
    timeout: 10000,
    success: function (data, textStatus, jqXHR) {
        // use either href or changePage but not both
        $.mobile.changePage("#NewPage");
    },
    error: function (jqXHR, textStatus, errorThrown) {
        alert("AJAX Error. Status: " + textStatus);
        // jqXHR.status
        // http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    }
});

Ответ 6

Вы должны поместить код перехода страницы в функцию успеха при вызове AJAX.

$.ajax({
    url:"request-url",
    data: data,
    type: "POST",
    success: function(response){
        // Add Transition Code Here
    }  
});