jQuery를 사용하지 않고 "data-"속성이있는 모든 요소를 ​​선택하십시오.


233

JavaScript 만 사용하면 특정 data-속성 을 가진 모든 DOM 요소를 선택하는 가장 효율적인 방법은 무엇입니까 data-foo? 요소는 다른 태그 요소 일 수 있습니다.

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

명심 document.querySelectorAllIE7에서 작동하지 않습니다. DOM 트리를 걷고 각 태그의 속성을 검사 하는 폴백 스크립트를 작성해야합니다 (실제로는 속도 querySelectorAll가 빠르지 않고 수동으로 태그를 검사해야 함).
tereško

jQuery를 사용하지 않는 이유는 무엇입니까? 이런 상황에서는 대체 할 수없는 일입니다 ...
James Hay

@hay는 전혀 순수 CSS에서 이러한 요소를 선택할 수도 있습니다.
Knu

1
@JamesHay 모든 환경, 회사, 사이트, 코딩 표준, 무엇을 가지고 있는지에 따라 jQuery를 사용할 수있는 것은 아닙니다. jQuery는 대체 할 수 없습니다.
Carnix

1
정말에 작동 난 아직 어떤 대답을 참조 해달라고 다른 data- : 요소, 즉 data-foo=0data-bar=1 data-app="js" data-date="20181231"
알렉스

답변:



243
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>

hasOwnProperty를 사용하여 지금까지 2016에서 나에게 가장 좋은 대답이 매우 빠르게 반복하는 다른 방법에 관한됩니다 MDN hasOwnProperty
NVRM

querySelectorAll ()의 NodeList는 반복 가능하지만 배열은 아닙니다. 로 반복 for in하면 길이 및 항목 속성이 반복됩니다. 대신 for of에 반복되도록 설계된 속성을 반복하여 사용하십시오.
Solvitieg

1

흥미로운 해결책은 다음과 같습니다 . 브라우저 CSS 엔진을 사용하여 선택기와 일치하는 요소에 더미 속성을 추가 한 다음 계산 된 스타일을 평가하여 일치하는 요소를 찾습니다.

그것은 스타일 규칙을 동적으로 생성한다. [...] 그런 다음 전체 문서를 스캔하고 (많은 속이고 IE 고유하지만 매우 빠른 document.all을 사용하여) 각 요소에 대해 계산 된 스타일을 얻는다. 그런 다음 결과 객체에서 foo 속성을 찾아 "bar"로 평가되는지 확인합니다. 일치하는 각 요소에 대해 배열에 추가합니다.


1
예, 오래된 브라우저에 대한 힌트를 제거했습니다.
Heinrich Ulbricht

대단히 선생님 감사;) 내가 5. 간과 고백해야
하인리히 울 브리 히트

예, 태그를 놓치기 쉽습니다. 그것이 html5이기 때문에 우리는 모두 document.querySelectorAll을 제안하고 있습니다 (그리고 data- * 속성은 html5에만 해당합니다).
shawndumas

-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을 싫어하게하지 않았다.
Loktar

1
값이 비싸고 (페이지의 모든 요소) 배열 리터럴 표기법 (예 : [])도 사용하며 작동하지 않습니다. 직접보십시오-> jsbin.com/ipisul/edit#javascript,html
shawndumas

2
OP는 어쨌든 HTML 5를 사용하고 있지만 이전 IE 빌드 getElementsByTagName에서는 전역 ( *) 선택기가 손상되었습니다. 재귀 DOM 검색이 작업을 수행하는 곳입니다. 속성에서 매핑 된 ElementNode에는 "data-foo"속성도 없습니다 data-foo. dataset객체를 찾고 있습니다 (예 : node.dataset.foo.

@shawndumas-그것은 당신이 PEBKAC 무엇이든 나타납니다. jsfiddle.net/D798K/2 . 효과가있다. 결국, 나는 어쨌든이 답변에 대해 -1을했다-나는 OP의 질문에서 "가장 효율적"이라는 단어를 놓쳤다 ...
Brian

@ 브라이언 -jsbin.com/ipisul 하나가 당신을 위해 작동합니까? 당신의 jsfiddle 하나 내 (작업 장소 요구)
ie9

-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

9
또한 이러한 문제에 대해 듣고 싶습니다.
Sean_A91 1

4
이제, 우리는 그것이 어떤 리터인지 알 수 없습니다. SO의 영원한 미스터리를위한 또 하나의 챕터
brasofilo

이것을 downvoting. 그것은 querySelectorAllAPI 로 완전히 오버 코딩되고 불필요합니다
dman
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.