2

jQueryMobileナビゲーションのページイベントを理解しようとしていますが、一部のイベントハンドラーが数回呼び出されるため、非常に奇妙な動作が見つかりました。

home.htmlとdisclaimer.htmlの2つのページがあります。どちらにも同じヘッダーが含まれています。

<head>
    <script src="js/jquery-1.8.2.min.js"></script>
    <script src="js/events.js"></script>
    <script src="js/jquery.mobile-1.2.0.min.js"></script>
</head>

ページのhome.htmlには次のリンクがあります。

<section data-role="page" id="home">
    <a href="#" id="test">Test</a>
</section>

そして、ファイルevents.jsには次のコードがあります。

var i = 0;

$(document).on('pageinit', 'section#home', function(event) {
    console.log(i++, 'pageinit');
    $('a#test').on('click', function() {
        console.log(i++, 'click pageinit');
    });
});

$(document).on('pagebeforeshow', 'section#home', function(event) {
    console.log(i++, 'pagebeforeshow');
    $('a#test').on('click', function() {
        console.log(i++, 'click pagebeforeshow');
    });
});

次に、次の手順を実行します。

  1. home.html(http)に移動します
  2. リンクをクリックしてください
  3. disclaimer.html(ajax)に移動します
  4. home.html(ajax)に移動します
  5. リンクをクリックしてください

次のコンソール出力を使用します。

0 "pageinit"             // step 1
1 "pagebeforeshow"
2 "click pageinit"       // step 2
3 "click pagebeforeshow"
4 "pagebeforeshow"       // step 4
5 "click pageinit"       // step 5
6 "click pagebeforeshow"
7 "click pagebeforeshow" 

理にかなっていますよね?しかし、今では奇妙な部分です。ページにアクセスする順序を変更すると、動作が変わります。

  1. disclaimer.html(http)に移動します
  2. home.html(ajax)に移動します
  3. リンクをクリックしてください
  4. disclaimer.html(ajax)に移動します
  5. home.html(ajax)に移動します
  6. リンクをクリックしてください

コンソール出力:

0 "pageinit"             // step 2
1 "pagebeforeshow"
2 "click pageinit"       // step 3
3 "click pagebeforeshow"
4 "pageinit"             // step 5
5 "pagebeforeshow"
6 "click pageinit"       // step 6
7 "click pagebeforeshow" 

これは奇妙なことです。6番目と7番目の結果が重複していると予想されるからです。

非常に長い質問でごめんなさい。誰かが私に何が起こっているのかを正確に説明してくれることを願っています。これが予想される動作であるかどうか。

tldr; jQueryMobileのイベントをどこでリッスン(クリック)しますか?

4

1 に答える 1

1

要するに、jQueryMobile では、内部でイベントをリッスン (バインド) する必要がありますpageinitreadyこれは、jQuery のイベントとほぼ同等です。そして、それはjQueryMobileの人たちが推奨するものです。

pageinitページが読み込まれて初期化されると (AJAX または HTTP を介して)pagebeforeshowトリガーされますが、jQueryMobile ダイアログを閉じた後など、ページが既に DOM にある場合は複数回トリガーされることがあります。バインドしたpagebeforeshowものは、ページが再度表示されるたびに再バインドされます。そのため、pagebeforeshow を 2 回クリックします

編集: テストの説明

2 つの html ページと js ファイルを複製し、両方のテストですべての手順を繰り返しました。

最初のテストでは、次のものがあります。

  1. home.html (http)に移動します。ページが初期化され、表示される予定だったため、(ドキュメントの委任によって) バインドし、(ログ 0 と 1)pageinitをトリガーします。pagebeforeshowこれにより、他の 2 つの関数もリンクにバインドされます (重要: この場合は委任ではなく、直接バインドです!)。このテストで「events.js」が読み込まれて実行されるのはこのときだけです。
  2. リンクをクリックします。ステップ 1 のため、これにより click pageinitclick pagebeforeshowの両方が期待どおりに実行されます(ログ 2 および 3)。
  3. disclaimer.html (ajax) に移動します。ログは表示されません。
  4. home.html (ajax) に移動します: "home.html" はまだ DOM にあるためpagebeforeshow、ログ (4) でわかるように、これがトリガーされます。これにより、リンク内のバインディングも実行されます。注: このステップで "disclaimer.html" が DOM から削除されたと思われます (これについては 2 番目のテストで詳しく説明します)。
  5. リンクをクリックします。最初の 2 つはステップ 1 のため、最後の (複製された) はステップ 4 のためのツリー ログを示します。

2 番目のテストでは、次のものがあります。

  1. disclaimer.html (http) に移動します。 と をバインドpageinitpagebeforeshowますが、イベントがトリガーされていないため、ログは表示されません。両方のイベントがdocument(委譲によって) バインドされているため、特定のページがまだ DOM にないかどうかは問題ではありません。このテストで「events.js」が読み込まれて実行されるのはこのときだけです。
  2. home.html (ajax) に移動: トリガーさpageinitれ、pagebeforeshowログ 0 と 1 が表示されます。両方のイベントがトリガーされると、対応するクリック イベントがリンクにバインドされます (直接バインド!)。
  3. リンクをクリックします。このステップでは、予想どおり、ログ 2 と 3 が表示されます。
  4. disclaimer.html (ajax) に移動します: ログには何も表示されません... しかし: jQueryMobile は「home.html」を DOM から削除する必要があると判断しました! これは、別のページに移動すると、JQM がすべてのページを削除するためです。「disclaimer.html」は DOM から削除されないことに注意してください。彼はその「所有者」であるためです。
  5. home.html (ajax) に移動します。ログ 4 と 5 でわかるように、このステップではpageinitandがトリガーされます (両方のイベントがまだドキュメント オブジェクトにバインドされているため)。これにより、ステップ 2 と同様に、2 つの関数がリンクにバインドされます。pagebeforeshowしかし... (次のステップを参照)
  6. リンクをクリックしてください: 「6 番目と 7 番目の結果が重複していると思われる」と言ったところです。ページ全体 (リンクを含む div) とそのすべてのコンテンツが DOM から削除され、 (ステップ 2 で) リンクに直接バインドした最初のクリック イベントがなくなったため、それらは複製されませんでした! そのため、手順 5 のバインドによって発生したログのみが表示されます。

JQMイベントがどのように機能するかを(最終的に)理解した場合、(完全なHTTPリクエストを介して)ロードされた最初のページは、ユーザーが外部ページに移動するか、(F5またはCTRL + Rを介して)ページをリロードするまでDOMに保持されます。他のページ (AJAX 経由で読み込まれる) は「メイン」DOM に追加され、別のページに移動すると、そこからアンロード/削除されます。したがって、すべてのバインドをpageinit(直接バインドするか、せいぜいその親 div[data-role:page] に委任する) を行う場合、イベント バインドの重複について心配する必要はありません。

PD: 私の書き方がおかしくなったとしたら、それはおそらく、私が受動態で英語を話したり書いたりすることに慣れていないためです。また、前置詞を混同することもあります :P

于 2012-12-07T02:10:10.017 に答える