【问题标题】:Select all elements with a "data-xxx" attribute without using jQuery在不使用 jQuery 的情况下选择具有“data-xxx”属性的所有元素
【发布时间】:2011-10-28 09:54:09
【问题描述】:

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

元素可能不同,例如:

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

【问题讨论】:

  • 请记住,document.querySelectorAll 不适用于 IE7。您必须创建一个备用脚本,该脚本将 walk DOM 树并检查每个标签中的属性(实际上我不知道 querySelectorAll 有多快,并且会手动检查标签) .
  • @hay 根本无法在纯 css 中选择这些元素。
  • @JamesHay 因为不是每个环境、公司、站点、编码标准,你有什么,都允许使用 jQuery。 jQuery 并非不可替代。
  • @Carnix 同意。除非您已经在使用它,否则使用 jQuery 将不再有意义,即使那样我也可能会选择退出。 6 年前,在您的站点中使用 jQuery 更为普遍,支持 IE5-8 更为普遍,而 jQuery 提供的抽象在一个简单的内衬中完成此操作。
  • 我仍然没有看到任何真正适用于 不同 data- 元素的答案,即:data-foo=0data-bar=1 @987654329 @ data-date="20181231"

标签: javascript html dom


【解决方案1】:

你可以使用querySelectorAll:

document.querySelectorAll('[data-foo]');

【讨论】:

  • 完美,谢谢!半相关注意:如果要选择名称中带有冒号的属性,则需要将冒号转义(至少在 Chrome 中),如下所示: querySelectorAll('[attribute\\:name]') (参见:@ 987654322@)
  • 这实际上并没有回答问题的标题。我不想选择“data-foo”。我想在“data-foobar”、“data-bar”、“data-name-i-dont-know”中选择“data-*”
  • @gman 原标题的意图被this edit无意中改变了。我现在已经恢复了。
【解决方案2】:
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。
【解决方案3】:
document.querySelectorAll('data-foo')

获取具有属性 data-foo 的所有元素的列表

如果您想获取具有某些特定值的数据属性的元素,例如

<div data-foo="1"></div>
<div data-foo="2" ></div>

我想获取 data-foo 设置为“2”的 div

document.querySelector('[data-foo="2"]')

但是,如果我想将数据属性值与某个变量的值相匹配,比如我想在 data-foo 属性设置为 i 时获取元素,那么问题来了。

var i=2;

因此您可以使用模板文字动态选择具有特定数据元素的元素

document.querySelector(`[data-foo="${i}"]`)

请注意,即使您不在字符串中写入值,它也会像我写的那样转换为字符串

<div data-foo=1></div>

然后在 Chrome 开发者工具中检查该元素,该元素将如下所示

<div data-foo="1"></div>

您也可以通过在控制台中编写以下代码来交叉验证

console.log(typeof document.querySelector(`[data-foo]="${i}"`).dataset('dataFoo'))

为什么我写 'dataFoo' 虽然属性是 data-foo 原因数据集属性被转换为 camelCase 属性

我参考了下面的链接

https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/data-* https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto/Use_data_attributes

这是我在 stackoverflow 上的第一个答案,请告诉我如何改进我的答案写作方式。

【讨论】:

    【解决方案4】:

    Try it → here

        <!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
    • querySelectorAll() 中的 NodeList 是可迭代的(尽管不是数组)。使用for in 循环将遍历长度和项目属性。相反,使用for of 来迭代旨在被迭代的属性
    【解决方案5】:

    Here 是一个有趣的解决方案:它使用浏览器 CSS 引擎为匹配选择器的元素添加一个虚拟属性,然后评估计算的样式以找到匹配的元素:

    它会动态创建样式规则 [...] 然后扫描整个文档(使用 很多谴责和 IE 特定但非常快的 document.all) 并获得 每个元素的计算样式。然后我们寻找 foo 结果对象上的属性并检查它是否评估为 “酒吧”。对于每个匹配的元素,我们添加到一个数组中。

    【讨论】:

    • 对,我去掉了关于旧浏览器的提示。
    • 是的,很容易错过标签。因为它是 html5,所以我们都建议 document.querySelectorAll (并且 data-* 属性也是 html5 特定的)。
    【解决方案6】:
    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/

    【讨论】:

    • 您的大部分“正确”只是不正确。我很确定有人给了你-1,因为你做了很多额外的工作来获取元素,然后将集合放入一个数组中。当没有任何解释时,我没有给出-1只是不喜欢。
    • 昂贵(页面上的所有元素),也使用数组文字表示法(即[]),并且在它之上,它不起作用。自己看 --> jsbin.com/ipisul/edit#javascript,html
    • 尽管 OP 无论如何都在使用 HTML 5,但带有全局 (*) 选择器的 getElementsByTagName 在较旧的 IE 版本中已损坏。这是递归 DOM 搜索完成工作的地方。从 data-foo 属性映射的 ElementNode 上也没有“data-foo”属性。您正在寻找 dataset 对象(即:node.dataset.foo.
    • @shawndumas - 看起来你所拥有的都是 PEBKAC。 jsfiddle.net/D798K/2。有用。最终,无论如何,我都会为这个答案给自己 -1 - 我错过了 OP 问题中“最有效”的词......
    • @Brian - jsbin.com/ipisul 对你有用吗?因为你的 jsfiddle 不能在我的(工作场所要求的)ie9 中工作......
    【解决方案7】:

    虽然不如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

    【讨论】:

    • querySelectorAll 的一系列问题是什么?
    • 我也很想听听这些问题。
    • 现在,我们永远不会知道那是哪一连串。 SO的永恒之谜又一章
    • 对此表示反对。 querySelectorAll api 完全过度编码并且没有必要
    • 这个问题可能有点过头了,但正如 OP 所要求的那样,它是一个编码良好的解决方案,纯香草。如果您还不知道 document.querySelectorAll 与您可以迭代和查找元素的众多其他方法相比有多慢,那么您不应该对此表示反对。我认为这是对可能性的一个很酷的演示,
    猜你喜欢
    • 2021-05-13
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 2012-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-19
    相关资源
    最近更新 更多