4

古いブラウザのフォールバックについては心配していません。また、ライブラリは使用できません。

イベントオブジェクトがあります。私はmatchesSelectorを介してcssセレクターに対してevent.targetをテストしています:

event['target'].matchesSelector('css selector here');

これは、次のように機能します。

event['target']['parentElement'].matchesSelector('css selector here');

...と:

event['target']['parentElement']['parentElement'].matchesSelector('css selector here');

私が探しているのは、forループなしで各parentElementが一致するかどうかを確認するために使用できる、私の理解を超えたいくつかの可能なオブジェクトメソッドです。私の焦点は効率です。

ありがとう!

4

4 に答える 4

8

close ()関数は、必要なことを実行します。

要素自体から開始し、指定されたselectorStringに一致するノードが見つかるまで、親をトラバースします(ドキュメントルートに向かって)。parents()jQueryの関数にやや似ています。

したがって、コードは次のようになります。

event.target.closest(selectorString)
于 2019-09-19T02:12:21.940 に答える
4

matchesSelector()ターゲット要素のすべての親要素を介した冗長なループを防ぐために、元のセレクターとスペースとで構成される追加のコンテキストセレクターを連結したセレクターを使用して、要素がセレクターと一致する要素の内部にあるかどうかをすばやく確認できます。ターゲット要素のタグ名:

function getAncestorBySelector(elem, selector) {
    if (!elem.matchesSelector(selector + ' ' + elem.tagName)) {
        // If element is not inside needed element, returning immediately.
        return null;
    }

    // Loop for finding an ancestor element that matches your selector.
}
于 2012-12-17T16:17:27.970 に答える
4

Marat Tanalinのソリューションは問題ありませんが、の標準構文elem.matchesSelectorelem.matches

function getAncestorBySelector(elem, selector) {
    if (!elem.matches(selector + ' ' + elem.tagName)) {
        // If element is not inside needed element, returning immediately.
        return null;
    }

    // Loop for finding an ancestor element that matches your selector.
}

残念ながら、まだすべてのブラウザがこの構文をサポートしているわけではありません。いくつかのブラウザはまだプレフィックスバージョンを実装しており、OperaMinielem.matchesSelectorはこの機能をまったくサポートしていません。

この問題を軽減するために、MDNによって提案されているように、説明されているアプローチを次のポリフィルと組み合わせることができます。

if (!Element.prototype.matches) {
    Element.prototype.matches = 
        Element.prototype.matchesSelector || 
        Element.prototype.mozMatchesSelector ||
        Element.prototype.msMatchesSelector || 
        Element.prototype.oMatchesSelector || 
        Element.prototype.webkitMatchesSelector ||
        function(s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;            
        };
}

または、完全に破棄することを検討してelem.matchesSelector、次のようなものを使用することもできます。

function getAncestorBySelector(elem, selector) {
    if([].indexOf.call(document.querySelectorAll(selector + ' ' + elem.tagName), elem) === -1) {
        // If element is not inside needed element, returning immediately.
        return null;
    }
    // Loop for finding an ancestor element that matches your selector.
}

どちらの実装でも、少なくとも、のサポートが必要ですquerySelectorAll。これは、最新のすべてのブラウザでサポートされている機能です。

ブラウザのサポート:

ここに画像の説明を入力してください

于 2016-05-03T22:26:22.647 に答える
1

vanilla-jsでのjQueryのメソッドの再実装を求めるほとんどの質問はparents()、この質問の複製として閉じられます。jQueryの動作をより適切にエミュレートするより現代的な例を提供したいと思います。

Typescript:

function getAllParentElements(child: HTMLElement, selector: string = '*') {
    const parents: HTMLElement[] = [];

    let parent: HTMLElement = child.parentElement?.closest(selector);
    while (parent) {
        parents.push(parent);
        parent = parent.parentElement?.closest(selector);
    }

    return parents;
}

Javascript:

function getAllParentElements(child, selector = '*') {
    const parents = [];

    let parent = child.parentElement && child.parentElement.closest(selector);
    while (parent) {
        parents.push(parent);
        parent = parent.parentElement && parent.parentElement.closest(selector);
    }

    return parents;
}
getAllParentElements(childEl); // -> return all ancestors including body & html elements
getAllParentElements(childEl, '.foo'); // -> return all ancestors with `.foo` class
于 2020-09-08T15:45:10.113 に答える