选择所有具有“ data-”属性的元素,而无需使用jQuery


233

仅使用JavaScript,选择具有特定data-属性(假设data-foo)的所有DOM元素的最有效方法是什么。元素可以是不同的标签元素。

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

请记住,这document.querySelectorAll不适用于IE7。您将必须创建一个后备脚本,该脚本将遍历 DOM树并检查每个标签中的属性(实际上,我不知道速度有多快querySelectorAll,并且会手动检查标签)。
tereško

您不使用jQuery的原因是什么?在这种情况下这几乎是不可替代的……
James Hay

@hay根本没有,您甚至也可以在纯CSS中选择这些元素。
2011年

1
@JamesHay因为不是每个环境,公司,站点,编码标准,您拥有什么,都允许使用jQuery。jQuery并非不可替代。
Carnix

1
我仍然看不到任何对不同 data-元素都有效的答案,即:data-foo=0and data-bar=1 and data-app="js" and data-date="20181231"
Alex

Answers:



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

将为您提供具有该属性的所有元素。

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

只会得到值为1的那些。


如何设置获得的元素的值?
史蒂文·阿吉拉尔

@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 2016年

querySelectorAll()中的NodeList是可迭代的(尽管不是数组)。与循环for in将遍历length和item属性。取而代之的是使用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 2011年

2
尽管OP仍在使用HTML 5,但在较旧的IE版本中,getElementsByTagName使用global(*)选择器已被破坏。这是递归DOM搜索完成工作的地方。从data-foo属性映射的ElementNode上也没有“ data-foo” 属性。您正在寻找的dataset:对象(即node.dataset.foo

@shawndumas-看来您拥有的是PEBKAC。 jsfiddle.net/D798K/2。有用。最终,无论如何我都会为自己的答案-1 -我错过了OP的问题中“最高效”的字眼……
Brian

@Brian-jsbin.com/ ipisul一个对您有用吗?因为您的jsfiddle不在我的工作场所(要求工作的地方)ie9 ...
shawndumas 2011年

-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 '16

4
现在,我们永远不会知道那是哪一连串。SO带来的关于永恒之谜的
又一

对此表示反对。querySelectorAllapi
对它
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.