4

ページ上の要素が対象となるすべてのイベントをキャプチャするために、Javascript を使用して CSS:target疑似クラスをエミュレートしようとしています。3 つのトリガー イベントを特定しました。

  1. window.location.hash初期化時にすでに同じ ID の要素をターゲットにしています
  2. 要素を対象とするアンカーがクリックされた
  3. イベントは上記hashchangeとは無関係に発生します (たとえば、window.historyAPI 経由) 。

シナリオ 2 は、clickイベントのpreventDefault. このシナリオの簡略化されたコードは次のとおりです。

$('body').on('click', 'a[href*=#]', function filterTarget(clickEvent){
    $(this.hash).trigger('target', [clickEvent]);
});

シナリオ 3 を実装しようとすると、問題が発生します。

$(window).on('hashchange', function filterTarget(hashChangeEvent){
    $(this.hash).trigger('target', [hashChangeEvent]);
});

targetハンドラーがシナリオ 2 のネイティブ動作をキャンセルしないhashchange場合、ネイティブ動作が結果のイベントを引き起こすと、ハンドラーは再びトリガーされます。これらのエッジケースを除外するにはどうすればよいですか?

ソリューション後の編集:

ローストの答えが鍵を握っていました—名前空間付きのhashchangeイベントを処理し、クリックハンドラーとそのpreventDefault内で処理されるロジックに基づいてハンドラーをアンバインドおよび再バインドします。完全なプラグインをここに書きました

4

3 に答える 3

5

私がそれを理解していれば、アンカータグがクリックされた場合に hashchange イベントを発生させたくないでしょう。次に、名前空間イベントを使用してロジックを設定できます。

デモ

$('body').on('click', 'a[href*=#]', function (clickEvent) {
    filterTarget(clickEvent,this);  
    $(window).off('hashchange.filter').on('hashchange.tmp', function () {
          $(this).off('hashchange.tmp').on('hashchange.filter', filterTarget);
    });
});
$(window).on('hashchange.filter', filterTarget);

function filterTarget(event,elem) {
    $(elem?elem.hash:window.location.hash).trigger('target', [event]);
    //you could filter depending event.type
    alert(event.type + '::'+ (elem?elem.hash:window.location.hash));
}
于 2013-07-30T13:25:17.787 に答える
0

preventDefault を呼び出す場合は、クリックの代わりに mousedown を使用できるようです。その場合、おそらくハッシュ変更はトリガーされません。

于 2013-07-29T05:52:34.750 に答える