querySelectorAll用于分组数据属性

时间:2018-06-09 22:33:28

标签: javascript dom

假设我有以下标记......

<div data-namespace-title="foo"></div>
<div data-namespace-description="bar"></div>
<div data-namespace-button="foo"></div>

无论如何,我可以用querySelectorAll选择它们吗?

我已经尝试了document.querySelectorAll([data-namespace-*]),但这当然不起作用

3 个答案:

答案 0 :(得分:1)

没有简单的方法,只是因为浏览器没有在属性名称/键上实现通配符选择器(仅限于其值)。你可以做的是简单地遍历你的元素集(在这种情况下,它们的公分母是div),然后过滤掉它们。

您可以通过调用<Node>.attributes来访问每个DOM节点的属性列表,然后将其转换为数组,并检查每个属性name中的一个或多个是否与正则表达式模式匹配{{ 1}}:

/^data-namespace-.*/gi
var els = document.querySelectorAll("div");
var filteredEls = Array.prototype.slice.call(els).filter(function(el) {
  var attributes = Array.prototype.slice.call(el.attributes);
  
  // Determine if attributes matches 'data-namespace-*'
  // We can break the loop once we encounter the first attribute that matches
  for (var i = 0; i < attributes.length; i++) {
    var attribute = attributes[i];
    
    // Return the element if it contains a match, and break the loop
    if (attribute.name.match(/^data-namespace-.*/gi))
        return el;
  }
});

console.log(filteredEls);

更新:如果您熟悉ES6,它会变得更加清晰,因为:

  • 我们可以使用Array.from代替繁琐的<div data-namespace-title="foo">title</div> <div data-namespace-description="bar">description</div> <div data-namespace-button="foobar">button</div> <div data-dummy>dummy</div>。专业提示:您也可以使用点差运算符,即Array.prototype.slice.call(...)
  • 我们可以使用Array.some代替手动创建带有返回逻辑的const els = [...document.querySelectorAll("div")]循环

for
const els = Array.from(document.querySelectorAll("div"));
const filteredEls = els.filter(el => {
  const attributes = Array.from(el.attributes);
  
  return attributes.some(attribute => attribute.name.match(/^data-namespace-.*/gi));
});

console.log(filteredEls);

答案 1 :(得分:1)

不确定您是否愿意更改属性的格式,但如果您想使用querySelectorAll

,那么将它们设置为相同并添加额外的属性可能会有用

Array.from(document.querySelectorAll('[data-namespace]')).forEach(el => {
  console.log(el.getAttribute('data-value'))
})
<div data-namespace="title" data-value="foo"></div>
<div data-namespace="description" data-value="bar"></div>
<div data-ns="button" data-value="foo"></div>
<div data-namespace="button" data-value="foo"></div>

您的另一个选择是使用xpath。

注意:使用iterateNext()时,如果您在调用文档之前修改文档,它将会中断。

var divs = document.evaluate('//@*[starts-with(name(.), "data-namespace")]', document, null, XPathResult.ANY_TYPE, null);

var div = divs.iterateNext()

while (div) {
  alert(div.ownerElement.textContent)
  div = divs.iterateNext()
}
<div data-namespace-title="foo">Foo</div>
<div data-namespace-description="bar">Bar</div>
<div data-ns-button="foo">NS Foo</div>
<div data-namespace-button="foo">Foo</div>

答案 2 :(得分:0)

这样的事情没有内置的选择器,但你仍然可以通过选择所有元素然后过滤那些具有以data-namespace开头的属性的方式来轻松完成它: / p>

&#13;
&#13;
console.log(
  [...document.querySelectorAll('*')]
    .filter(({ attributes }) =>
      [...attributes].some(({ name }) => name.startsWith('data-namespace'))
    )
);
&#13;
<div data-baz="baz"></div>
<div data-namespace-title="foo"></div>
<div data-namespace-description="bar"></div>
<div data-namespace-button="foo"></div>
&#13;
&#13;
&#13;