2

背景
私は、jQuery Mobile アプリのアンカー要素でクリック イベントが発生したときに、リンクの方向をキャンセルしようとするこのばかげた小さな問題に苦労してきました。

次のような単純な複数ページのドキュメントがあるとします。

<div data-role="page" id="page-1">          
    <div data-role="content">
        <a href="#page-2" id="mLink">page 2</a>
    </div><!-- /content -->
</div><!-- /page -->

<div data-role="page" id="page-2">
    <div data-role="content">
    </div><!-- /content -->
</div><!-- /page -->

... そして JavaScript は次のようになります:

(function (MyApp, $, undefined) {
    'use strict';

    // Initializes app
    function init() {       
        $('#mLink').on('click', function (event) {
            event.preventDefault();
            //event.stopPropagation();
            //event.stopImmediatePropagation();

        });
    }

    // jQuery Mobile is ready now -> override defaults
    $(document).on("mobileinit", function () {
        // Set the default page transition
        $.mobile.defaultPageTransition  = 'slide';
    });

    // jQuery Mobile is ready now 
    $(document).ready(init);

}(window.MyApp = window.MyApp || {}, jQuery));

問題がページ遷移をキャンセルしない
理由がわかりません。event.preventDefault()ただし、追加event.stopPropagation()するとキャンセルされます。また、アプリから jQuery Mobile ライブラリを削除すると、.xml がなくても動作しevent.stopPropagation()ます。

質問
これは通常の動作ですか? リンク方向をキャンセルするためにハンドラーで常に両方を呼び出しても問題ありませんか?

注記
jQuery Mobile は、マルチページ テンプレート、ナビゲーション、およびトランジション機能のためだけに使用しています。

追加の質問
私の最初の質問の種類の背後に潜んでいる質問は、 「リンクのデフォルト アクション、つまりターゲット ページへの移動を妨げないようにするために、 event.preventDefault() メソッドをインターセプトするリンクに対して、jQuery Mobile は何をするのか?」というものでした。

4

2 に答える 2

6

普通?はい。両方に電話してもよろしいですか?はい。
event.preventDefault()ブラウザーの既定の動作をevent.stopPropagation()防止するために必要な唯一のツールであり、競合するイベント ハンドラーの起動を防止するために必要な唯一のツールです。

ワンライナーが必要な場合は、 を使用return falseして同じ結果を得ることができます。http://api.jquery.com/on/から:

イベント ハンドラから false を返すと、自動的に event.stopPropagation() と event.preventDefault() が呼び出されます。function(){ return false; の省略形として、ハンドラーに false 値を渡すこともできます。}。したがって、 $("a.disabled").on("click", false); クラスが「disabled」のすべてのリンクにイベント ハンドラーをアタッチします。これにより、クリックされたときにリンクをたどることができなくなり、イベントのバブリングも停止します。

于 2012-08-16T20:23:23.317 に答える
3

私は jQuery モバイルにあまり詳しくないことを認めなければなりませんが、これにはまったく驚かされません。最近、モバイル デバイス (純粋な JS) 用のスクリプトをいくつか書きましたが、最初に気付くのは、それらのほとんどでクリック イベントがまったくないことです。すべてが今タッチです。

問題は、タッチ イベントが非常に過負荷になっていることです。ユーザーが画面に触れて X 時間保持すると、拡大鏡を取得するためにテキストを選択しようとしているか、最初のタッチがスワイプの開始である可能性があります。で実行されるデフォルトのアクションは実際にはありませんtouchstart。イベントを提供するほとんどのスクリプトは、リスナーを Xms の touched 要素にバインドするイベントtabのリスナーを追加し、それを.touchstarttouchendclick

Prevent default allow はイベント自体を停止せず、そのデフォルト アクション (存在する場合) は失敗しませんが、イベントは dom を介して伝播し、touchend リスナーが設定され、そのハンドラーがキックするハンドラーになります。すべてオフ。touchoutデフォルトのアクションを阻止するのではなく、イベントが DOM をさらに下ってそのターゲットに向かって伝播するのを止めるだけの場合、ハンドラーがバインドされることはなく、少なくとも起動されることはないと思います。簡単に言えば、要素に関する限り、touchstartイベントが到達したことはないため、 atouchendなしで a が起動された場合は発生しませんでした。これtouchstartは、タッチが DOM の他の場所で開始されたことを意味するに違いありません。

それが、この少し予期しない動作が発生する理由を説明していると思います。今あなたの質問:

jQuery モバイルがないと、クリック ハンドラーが呼び出されます。タッチ デバイスには実際のクリック イベントはないと言いましたが、リンクは要素に直接バインドされているクリック ハンドラーを起動します。ただし、モバイル デバイスではクリック イベントを実際に委任することはできません。直接バインディングだけがうまくいくようです。おそらく、バブリング段階でそれらを捕まえることができるかもしれませんが、アンカーの場合、オプションが少し制限されすぎます. あなたのスニペットでは、クリックハンドラーを要素に直接バインドしているため、jQm ではなく通常の jQ で機能する理由を説明できます。

正常な動作ですか?はい、そう思います。私の経験ではそうです。イベントを停止するために両方のメソッドを呼び出しても問題ありませんか? もちろん、2 つの違いが何であるかを知っていて、いつ、なぜ 1 だけを呼び出すかを知っている限り. しかし、イベントを殺したい場合は、両方を呼び出しても害はないと思います.

注:すでに与えられた両方の回答は、 と の両方をreturn false;呼び出すことと同じになると言います。これは jQuery には当てはまりますが、純粋な JS を書いている場合はそうではありません。純粋な JavaScript では、ハンドラから false を返すことは、単に を呼び出すことと同じなので注意してください。MS の JScript 実装は、この良い例です。stopPropagationpreventDefaultpreventDefault

//w3c:
e.preventDefault();
e.stopPropagation();
//IE:
e.returnValue = false;
e.cancelBubble = true;

ハンドラーが false を返す === イベント オブジェクトの戻り値は ですfalseが、そのバブル機能は変更されていません。

于 2012-08-16T20:58:59.270 に答える