3

私は最も素晴らしいアイデアを探しています。焦点は効率です-ループの束を避けてみましょう=)

ライブラリはありません。これは純粋なJSの天才の練習です。ただし、これを実現する場合は、ライブラリ内から関数を自由に参照してください。くだらない古いブラウザ(つまり、IE)へのフォールバックの必要はありません。

セットアップ

イベントの委任を作成しようとしています。この要素内で発生する各イベントタイプ(クリック、mouseenterなど)のコンテナ要素(コンテキスト)にイベントリスナーをバインドしています。リスナーは関数を参照します。これを「ルート」と呼びます。

個別に作成された、次のようなオブジェクトがあります(例)。

myarr['click']['.myclass'] = functionReference1;
myarr['click']['#myid'] = functionReference2;
myarr['click']['div>a'] = functionReference3;

routeテイク(ここevent.typeでは「クリック」)してmyarrに移動し、すべてのclickレコードを取得します。route次に、各セレクターキーをループして、それを。と照合しevent.targetます。一致する場合は、関数参照が呼び出されcallbackます。

これはすべてうまくいっています。かなり速く、簡単です。

質問

は、セレクターキーevent.targetに一致する要素の子である可能性があります。その親がコンテキスト要素との間にあるかどうかを判断するために、クレイジーで滑らかなブードゥー黒魔術を探しています。できれば、いくつかのネイティブブラウザ機能。event.target

理想的には、例として、私はの線に沿って何かをすることができます

context.querySelectorAll(key + " " + event.target);

しかし、明らかに、私が知る限り、オブジェクトをquerySelectorAllに渡すことはできません。

何が試されたのか

2つの方法が試されました。両方とも動作します。どちらもきれいではありません。

1)

一致するものが見つかるまで、event.target.parentNodeをループします。このトートはそれを行いますが、既存のループ内にループを作成します。ページにいくつかのセレクターキーと多くの要素があると、SLOWになり始めます。

if (event['target'].matchesSelector(key)) {
    //do callback
} else {
    var et = event['target'];
    while (et['parentNode'] !== null and et['parentNode'] !== this) {
        et = et['parentNode'];
        if (et.matchesSelector(key)) {
            //do callback
            break;
        }
    }
}

2)

範囲を使用します。私はこれをかなり誇りに思っていますが、同じマルチループの問題があります。パフォーマンスをあまりテストしていませんが、ここで発生することはたくさんあります。セレクターキーに一致する要素がたくさんある場合、これはおそらく効率を損なうことになります。

if (event['target'].matchesSelector(key)){
    //do callback
} else {
    var range2 = document.createRange();
    range2.selectNode(event.target);
    var range = document.createRange();         
    var allthese = document.querySelectorAll(key)
    for (var i = 0; i < allthese.length; i++){
        range.selectNode(allthese[i]);
        if (range2.compareBoundaryPoints(range2.START_TO_START, range) && range2.compareBoundaryPoints(range2.END_TO_END, range) <= 0){
            //do callback
            break;
        }
    }
}

MAGIC VOODOO-私にいくつか見つけてください、そして私が再び担当者を持っているとき、私は大きな報奨金を作成します。

4

2 に答える 2

3

多分あなたはこれを試してみるべきです:

event['target'].matchesSelector(key) || event['target'].matchesSelector(key + ' *')

ここで、2 番目の条件は、ターゲットがキー セレクターの子孫であるかどうかを確認します。

このJSFIDDLE (fiddle Works in webkit (prefer chrome) browser only) でわかるように、子/子孫は親セレクターを使用して一致します

PS:実際のキーに一致する要素も必要な場合、この方法は機能しませんが、質問で「その親がコンテキスト要素とevent.targetの間にあるかどうかを判断するためのクレイジーでスムーズなブードゥーの黒魔術」と言ったので、私は実際の要素が必要ないとします

于 2012-11-13T19:31:10.917 に答える
1

これはどう:

        if (event['target'].matchesSelector(key)) {
           //do callback
         } else {
            var allthese = document.querySelectorAll(key) //this array has order
           //use  "binary search" here to improve perfomance.
            for (var i = 0; i < allthese.length; i++){
                if(event['target'].compareDocumentPosition(allthese[i])&&DOCUMENT_POSITION_CONTAINS){
                    //do callback
                }
            }
        }
     }

二分探索のようなアルゴリズムを使用して、パフォーマンスを向上させることができます (これらはすべて順序付けられた配列です)。

compareDocumentPosition の戻り値は次のとおりです。

  • DOCUMENT_POSITION_DISCONNECTED 1
  • DOCUMENT_POSITION_PRECEDING 2
  • DOCUMENT_POSITION_FOLLOWING 4
  • DOCUMENT_POSITION_CONTAINS 8
  • DOCUMENT_POSITION_CONTAINED_BY 16
  • DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32

したがって、その配列「document.querySelectorAll(key)」を検索アルゴリズムで検索できます。

于 2013-04-02T10:19:01.090 に答える