简体   繁体   English

Select 不使用 jQuery 的所有具有“data-xxx”属性的元素

[英]Select all elements with a "data-xxx" attribute without using jQuery

Using only pure JavaScript, what is the most efficient way to select all DOM elements that have a certain data- attribute (let's say data-foo ).仅使用纯 JavaScript,什么是 select 具有特定data-属性(假设data-foo )的所有 DOM 元素的最有效方法。

The elements may be different, for example:元素可能不同,例如:

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

You can use querySelectorAll :您可以使用querySelectorAll

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

will get you all elements with that attribute.将为您提供具有该属性的所有元素。

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

will only get you ones with a value of 1.只会得到值为 1 的值。

document.querySelectorAll('data-foo')

to get list of all elements having attribute data-foo获取具有属性 data-foo 的所有元素的列表

If you want to get element with data attribute which is having some specific value eg如果您想获取具有某些特定值的数据属性的元素,例如

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

and I want to get div with data-foo set to "2"我想将 data-foo 设置为“2”的 div

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

But here comes the twist what if I want to match the data attirubte value with some variable's value like I want to get element if data-foo attribute is set to i但是,如果我想将数据属性值与某个变量的值匹配,比如如果 data-foo 属性设置为 i,我想获取元素

var i=2;

so you can dynamically select the element having specific data element using template literals因此您可以使用模板文字动态 select 具有特定数据元素的元素

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

Note even if you don't write value in string it gets converted to string like if I write请注意,即使您不在字符串中写入值,它也会像我写的那样转换为字符串

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

and then inspect the element in Chrome developer tool the element will be shown as below然后在 Chrome 开发者工具中检查该元素,该元素将如下所示

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

You can also cross verify by writing below code in console您还可以通过在控制台中编写以下代码来交叉验证

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

why I have written 'dataFoo' though the attribute is data-foo reason dataset properties are converted to camelCase properties为什么我写了“dataFoo”虽然属性是 data-foo 原因数据集属性被转换为 camelCase 属性

I have referred below links我在下面提到了链接

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

This is my first answer on stackoverflow please let me know how can I improve my answer writing way.这是我在 stackoverflow 上的第一个答案,请让我知道如何改进我的答案写作方式。

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>

Here is an interesting solution: it uses the browsers CSS engine to to add a dummy property to elements matching the selector and then evaluates the computed style to find matched elements: 是一个有趣的解决方案:它使用浏览器 CSS 引擎向匹配选择器的元素添加一个虚拟属性,然后评估计算的样式以找到匹配的元素:

It does dynamically create a style rule [...] It then scans the whole document (using the much decried and IE-specific but very fast document.all) and gets the computed style for each of the elements.它确实动态地创建了一个样式规则 [...] 然后扫描整个文档(使用大量 decried 和 IE 特定但非常快的 document.all)并获取每个元素的计算样式。 We then look for the foo property on the resulting object and check whether it evaluates as “bar”.然后,我们在生成的 object 上查找 foo 属性,并检查其计算结果是否为“bar”。 For each element that matches, we add to an array.对于每个匹配的元素,我们添加到一个数组中。

Native JavaScript's querySelector and querySelectorAll methods can be used to target the element(s).本机 JavaScript 的querySelectorquerySelectorAll方法可用于定位元素。 Use a template string if your dataset value is a variable.如果您的dataset值是变量,请使用模板字符串。

 var str = "term"; var term = document.querySelectorAll(`[data-type=${str}]`); console.log(term[0].textContent); var details = document.querySelector('[data-type="details"]'); console.log(details.textContent);
 <dl> <dt data-type="term">Thing</dt> <dd data-type="details">The most generic type.</dd> </dl>

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);
    }
}

Not sure who dinged me with a -1, but here's the proof.不知道是谁给我打了-1,但这是证据。

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

While not as pretty as querySelectorAll (which has a litany of issues), here's a very flexible function that recurses the DOM and should work in most browsers (old and new).虽然不如querySelectorAll漂亮(有很多问题),但这里有一个非常灵活的 function 递归 DOM 并且应该在大多数浏览器(旧的和新的)中都可以工作。 As long as the browser supports your condition (ie: data attributes), you should be able to retrieve the element.只要浏览器支持您的条件(即:数据属性),您应该能够检索该元素。

To the curious: Don't bother testing this vs. QSA on jsPerf.好奇的人:不要费心在 jsPerf 上测试这个和 QSA。 Browsers like Opera 11 will cache the query and skew the results.像 Opera 11 这样的浏览器会缓存查询并扭曲结果。

Code:代码:

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;
        }
    }
}

You can then initiate it with the following:然后,您可以使用以下命令启动它:

recurseDOM(document.body, {"1": 1}); for speed, or just recurseDOM(document.body);为了速度,或者只是recurseDOM(document.body);

Example with your specification: http://jsbin.com/unajot/1/edit您的规范示例: http://jsbin.com/unajot/1/edit

Example with differing specification: http://jsbin.com/unajot/2/edit不同规格的示例: http://jsbin.com/unajot/2/edit

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM