jQueryを使用せずに「data-」属性を持つすべての要素を選択する


233

JavaScriptのみを使用して、特定のdata-属性を持つすべてのDOM要素を選択する最も効率的な方法は何ですか(たとえば、としましょうdata-foo)。要素は異なるタグ要素である場合があります。

<p data-foo="0"></p><br/><h6 data-foo="1"></h6>

覚えておいてくださいdocument.querySelectorAllIE7上では動作しません。あなたは考えフォールバックするスクリプトを作成する必要があります歩いて DOMツリーをして(実際に私はどのように速くは考えていない各タグ内の属性をチェックquerySelectorAllし、タグの手動チェックのために行くだろうが)。
テレシュコ

jQueryを使用しない理由は何ですか?このような状況では、ほとんど置き換えられません...
ジェームズヘイ

@hayでは、純粋なCSSでこれらの要素を選択することもできません。
Knu 2011

1
@JamesHayは、jQueryの使用がすべての環境、会社、サイト、コーディング標準で許可されているわけではないためです。jQueryはかけがえのないものではありません。
Carnix 2017年

1
それでも、さまざま data-な要素で実際に機能する回答はありません。例:data-foo=0and data-bar=1 および data-app="js" and data-date="20181231"
Alex

回答:



244
document.querySelectorAll("[data-foo]")

その属性を持つすべての要素を取得します。

document.querySelectorAll("[data-foo='1']")

値が1のものだけが取得されます。


取得した要素の値をどのように設定できますか?
Steven Aguilar

@StevenAguilar .querySelectorAll()はを返しますNodeList。そのドキュメントに記載されているように、を使用してコレクションを反復処理できます.forEach()。これは非IEソリューションであることに注意してください:developer.mozilla.org/en-US/docs/Web/API/…。IEをサポートする必要がある場合は、通常のforループを使用してNodeListをループするだけで済みます。
Joseph Marikle

13

試す→こちら

    <!DOCTYPE html>
    <html>
        <head></head>
        <body>
            <p data-foo="0"></p>
            <h6 data-foo="1"></h6>
            <script>
                var a = document.querySelectorAll('[data-foo]');

                for (var i in a) if (a.hasOwnProperty(i)) {
                    alert(a[i].getAttribute('data-foo'));
                }
            </script>
        </body>
    </html>

2016年のこれまでのところ、hasOwnPropertyを使用するのが最良の答えです。これは、他の反復方法に関して非常に高速です Mdn hasOwnProperty
NVRM '29

querySelectorAll()からのNodeListは反復可能です(配列ではありません)。でループするfor inと、長さとアイテムのプロパティが繰り返されます。代わりに、for of反復するように設計されたプロパティを反復するために使用します
Solvitieg

1

ここで興味深いソリューションです:それは、セレクタに一致する要素にダミーのプロパティを追加するために、ブラウザのCSSのエンジンを使用して、マッチした要素を見つけるために、計算されたスタイルを評価します。

それは動的にスタイルルールを作成します[...]次に、ドキュメント全体をスキャンし(非常に非難されIE固有ですが非常に高速なdocument.allを使用)、各要素の計算されたスタイルを取得します。次に、結果のオブジェクトでfooプロパティを探し、それが「bar」として評価されるかどうかを確認します。一致する要素ごとに、配列に追加します。


1
右、古いブラウザに関するヒントを削除しました。
ハインリッヒウルブリヒト

あなたは非常に多くの先生に感謝;)私は5見落とさ告白しなければならない
ハインリヒ・ウルブリヒト

ええ、タグを見逃しやすいです。これはhtml5であるため、すべてdocument.querySelectorAllを提案しています(そしてdata- *属性もhtml5固有です)。
ショーンデュマ

-1
var matches = new Array();

var allDom = document.getElementsByTagName("*");
for(var i =0; i < allDom.length; i++){
    var d = allDom[i];
    if(d["data-foo"] !== undefined) {
         matches.push(d);
    }
}

誰が私に-1を付けたのかはわかりませんが、ここに証明があります。

http://jsfiddle.net/D798K/2/


3
あなたのほとんどが「正しい」だけではありません。誰かがあなたに-1を与えたと確信しています。なぜなら、要素を取得するために多くの余分な作業を行い、コレクションを配列に入れているからです。私は-1に説明がないときは-1をただ嫌悪することはしませんでした。
Loktar 2011

1
高価(ページ上のすべての要素)、また配列リテラル表記(つまり[])を使用し、その上では機能しません。自分で確認してください-> jsbin.com/ipisul/edit#javascript,html
shawndumas

2
OPはとにかくHTML 5を使用していますが、以前のIEビルドではgetElementsByTagNameグローバル(*)セレクターが壊れています。これは、再帰的なDOM検索が仕事を行う場所です。また、data-foo属性からマップされたElementNodeには "data-foo"プロパティはありません。あなたは探しているdataset:オブジェクト(すなわちnode.dataset.foo

@shawndumas-あなたが持っていたものは何でもPEBKACでした。 jsfiddle.net/D798K/2。できます。最終的に、私はとにかくこの答えを自分で-1にしたい-OPの質問で「最も効率的」という言葉を逃した...
ブライアン

@Brian -んjsbin.com/ipisulあなたのための1の仕事を?あなたのjsfiddleが私の(職場で要求された)ie9で動作していないのを引き起こします...
shawndumas

-4

ないきれいなほどの間にquerySelectorAll(問題の連祷を持っている)、ここではDOMを再帰と(新旧)ほとんどのブラウザで動作するはずです非常に柔軟な機能があります。ブラウザが条件(つまり、データ属性)をサポートしている限り、要素を取得できます。

奇妙なことに:jsPerfでこれとQSAをテストする必要はありません。Opera 11のようなブラウザはクエリをキャッシュし、結果を歪めます。

コード:

function recurseDOM(start, whitelist)
{
    /*
    *    @start:        Node    -    Specifies point of entry for recursion
    *    @whitelist:    Object  -    Specifies permitted nodeTypes to collect
    */

    var i = 0, 
    startIsNode = !!start && !!start.nodeType, 
    startHasChildNodes = !!start.childNodes && !!start.childNodes.length,
    nodes, node, nodeHasChildNodes;
    if(startIsNode && startHasChildNodes)
    {       
        nodes = start.childNodes;
        for(i;i<nodes.length;i++)
        {
            node = nodes[i];
            nodeHasChildNodes = !!node.childNodes && !!node.childNodes.length;
            if(!whitelist || whitelist[node.nodeType])
            {
                //condition here
                if(!!node.dataset && !!node.dataset.foo)
                {
                    //handle results here
                }
                if(nodeHasChildNodes)
                {
                    recurseDOM(node, whitelist);
                }
            }
            node = null;
            nodeHasChildNodes = null;
        }
    }
}

その後、次のように開始できます。

recurseDOM(document.body, {"1": 1}); スピードのため、または単に recurseDOM(document.body);

指定の例:http : //jsbin.com/unajot/1/edit

仕様が異なる例:http : //jsbin.com/unajot/2/edit


23
とんでもない問題はquerySelectorAll何ですか?
ShreevatsaR 2016

9
これらの問題についてもぜひお聞かせください。
Sean_A91 2016年

4
今、私たちはそれがどれであったかわからないでしょう。SOからの永遠の謎のためのもう1
つの章

これに反対票を投じます。querySelectorAllAPIで完全にコード化され、不要です
dman
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.