20

jquery-mobile(jqm)とノックアウトを使用して構築されたモバイルシングルページWebアプリケーションがあります。アプリケーション自体には複数のページがありますが、それらはすべて1つのHTMLドキュメントに含まれています。

問題:「ページのビューモデルの作成」を同期から非同期の動作に変更した後、データの準備ができる前にjquery-mobileがイベントを発生させるという問題があります。

背景:最近まで、サンプルデータ(基本的には巨大なJSONブロブ)を使用していて、すべてがスムーズに機能していました。さまざまなソースからのビューモデルの新しい非同期構成では、データはすぐには準備できず、私の「buildViewModel」メソッドは、データを同期的に返すだけでなく、継続コールバックを受け取ります。

pagebeforecreateイベントとpagebeforechangeイベントをサブスクライブし、コードを実行してここにビューモデルを設定します。問題は、イベントハンドラーから戻った後、データが使用可能になる前に、jqmが残りのイベントチェーンをトリガーすることです。これにより、ページが準備されていないページに遷移しますが、これは望ましくありません。

event.preventDefaultページをa)拡張し、b)ページ遷移を実行する準備ができたら、すべての前のイベントを呼び出して手動で$ .mobile.changePageを呼び出しようとしましたが、運がありませんでした。

jquery-mobileソースをスキャンしましたが、pagebeforeshowイベントを遅らせることができるように見えるものを見つけることができませんでした。これは、ページを適切にレンダリングできるようにするために基本的に必要なものです。

jquery-mobileがページの拡張を試みる前、およびページへの移行を実行する前に、1)データが利用可能であり、2)ノックアウトが適用されて初期DOM操作を実行していることを確認するにはどうすればよいですか?

同期ajaxを使用してリソースをフェッチすることも検討しましたが、これは(PhoneGap / Cordovaを使用して)デバイスからロードされたリソースでは機能せず、回避したい他の悪影響があります。

FWIW、クリックハンドラーをどこにでも配線して、すべてのナビゲーションイベントを手動で処理する必要をなくしたいのですが、必要に応じてすべてのソリューションを利用できます。

これが重複している場合はお詫びします。たくさんの質問を検索して読みましたが、まったく同じ答えや質問は見つかりませんでした。これは一般的なシナリオだと思うので、私がこの問題に最初に遭遇するのは信じられないことです。

更新:問題シナリオの説明を明確にしました。

4

6 に答える 6

13

私はこれとまったく同じ問題を抱えていました。

私が思いついた唯一の解決策は、Ajaxリクエストが完了するまで遷移の開始を延期するカスタム遷移ハンドラーを作成することです。

これがテクニックを示すフィドルです。フィドルはノックアウトを使用しませんが、遷移を延期する方法を示しています。

基本的に、$.ajax()promiseを返すので、それをデフォルトの遷移ハンドラーによって返されるpromiseにパイプして、新しいハンドラーから返すことができます。

私のpagebeforeshowハンドラーでは、Ajax Promiseをページにアタッチして、遷移ハンドラーがページにアクセスできるようにします。これが最善の方法かどうかはわかりませんが、グローバル変数を使用するよりも気に入っています。

これについて私が気に入らなかった唯一のことは、Ajax応答が到着するまで遷移の開始を遅らせることです。そのため、ページがユーザーに「ハング」して、ユーザーにもう一度クリックさせているように感じる可能性があります。読み込みメッセージを手動で表示すると、応答性が少し向上します。

これがお役に立てば幸いです。より良い解決策が見つかったらお知らせください。

于 2012-12-31T00:52:34.160 に答える
5

コンテンツの準備ができるまで新しいページへの移行を遅らせることは、jQueryMobileで動的コンテンツに直面する場合の非常に一般的な問題です。これに対処する最も便利な方法は次のとおりです。

  • 従来のhrefタイプのナビゲーションの代わりに、最初にコンテンツを取得し、DOMに新しいページを作成してから、を介してこの新しいページへの移行を開始する「クリック」アクションに基づいてリンクを作成します$.mobile.changePage。このアプローチの利点は、配置が簡単なことです。欠点は、従来のhrefリンクでナビゲートしないことです。

  • イベントをドキュメントレベルでバインドしてpagebeforechange、ナビゲーション時にターゲットページが動的コンテンツを含む必要があるページの1つであるかどうかを検出します。このような場合、デフォルトのナビゲーションが発生しないようにし、時間をかけてページを生成し、成功すると移行することができます。これは、動的に挿入されたコンテンツに関する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) 
                 */
              }
          }
    });
    
于 2013-01-02T09:04:15.070 に答える
3

ページ遷移を行う代わりに「ロード」関数を呼び出すようにリンクを設定します。ロード関数で、「ロードメッセージ」を表示し、JSON呼び出しを行います。最後に、JSONコールバック関数で、ページpage2に変更します

ロード機能:

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/

ユーザーが待機中にページ1の入力フィールドを更新できないようにする場合は、ページ1とページ2の間に「待機ページ」を導入し、「待機ページ」の初期化は「loadPage2」と同じようにすることに注意してください。 。

于 2013-01-04T00:31:59.750 に答える
0

応答からデータをバインドするすべてのウィジェットに対して再度起動する必要があると思います

たとえば、要素のtriggerwithcreateまたはrefrestevent を呼び出す必要があります$("#element").trigger('create'); 。JQueryMobileは、すべてのデフォルトイベントを要素にそのままバインドします。

- - 編集 - -

サンプルコードを作成しました。これはあなたの問題と同じだと思います。リンクhttp://jsfiddle.net/ndkhoiits/BneqW/embedded/result/を試してください。

データをレンダリングする前に、サービスを呼び出して表示用に取得する必要があります。そのため、jqmによってバインドされたすべてのイベントが削除されます。

これには回避策があります。要素に対してjqmを起動させないでください。すべてのデータが、knockoutjsによってバインドされた後にトリガーします。修正バージョン http://jsfiddle.net/ndkhoiits/c5a2b/embedded/resultを試してみましょう。 //

これはコードhttp://jsfiddle.net/ndkhoiits/c5a2b/です

于 2012-12-28T15:56:53.280 に答える
0

私は小さなjQueryMobile/ KnockoutJSアプリケーションを持っていて、まったく同じ問題に苦しんでいます。私のアプリには約5ページが含まれています。すべてが単一の物理HTMLドキュメントに含まれており、<div data-role="page">個々のページを分離する標準のマークアップが付いています。

私はついにクリックベースのナビゲーションと成功$.mobile.changePage()の結果として発砲しました。$.ajax

この手法の欠点の1つは、onclickvshref属性に依存しているときにボタンの強調表示が失われることです。私の関連記事を参照してください:hrefとスクリプト化されたページ遷移およびボタンの強調表示

href後で両方を提供することを選択し、JavaScriptロジックを呼び出してViewModelsなどをロードする際にナビゲーションを実行することに依存してonclickいます。これが問題であることがわかった唯一の場所は、ソースページで必要な検証が可能な場合です。失敗した場合、トランジションはすでに開始されており、UIがフラッシュバックしてソースページに戻ります。醜いですが、これは私のアプリ内の限られたインスタンスでのみ発生します。

これはノックアウトに固有のものではないと思います。私の正確な解決策は、モデルが完全にロードされる前にナビゲーションが完了する可能性があるという問題を提示する可能性がありますが、に依存している場合$.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
    }
});
于 2012-12-31T19:01:18.840 に答える
-2

ページ遷移のコードは、AJAX呼び出しのsuccess関数に配置する必要があります。

$.ajax({
    url:"request-url",
    data: data,
    type: "POST",
    success: function(response){
        // Add Transition Code Here
    }  
});
于 2012-12-28T18:10:46.290 に答える