不使用库而无法使用querySelectorAll时,按属性获取元素吗?


123
<p data-foo="bar">

你怎么做相当于

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

其中querySelectorAll不可用

我需要至少在IE7中有效的本机解决方案。我不在乎IE6。


签出sizzle.js javascript选择器库
纪元

1
不错,是我唯一需要做的选择是数据属性,因此我试图找出最简单的修补方法,而无需引入整个选择器引擎(例如Sizzle)。但是从源头上看很不错。顺便说一句,另一个很棒的选择器引擎是github.com/ded/qwery
ryanve

@ryanve,谢谢,我来看看:)
纪元

我使用的工作解决方案在github.com/ryanve/dope/blob/master/dope.js中,称为“ queryAttr”的方法
ryanve 2012年

7
大声笑,你的问题是我的答案。所以这带来了另一个问题。在什么情况下querySelectorAll不可用? note - I don't care all IE
vzhen 2013年

Answers:


136

您可以编写一个运行getElementsByTagName('*')的函数,并仅返回具有“ data-foo”属性的那些元素:

function getAllElementsWithAttribute(attribute)
{
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++)
  {
    if (allElements[i].getAttribute(attribute) !== null)
    {
      // Element exists with attribute. Add to array.
      matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

然后,

getAllElementsWithAttribute('data-foo');

8
使用!= null是一种理想的方式(比上面的评论更好),因为在旧的IE中,getAttribute可能返回的值typeof'number'
ryanve 2012年

1
为什么使用document.getElementsByTagName('*')代替document.all
pedrozath

1
为什么不使用hasAttribute而不是getAttribute() !== null,因为您只想检查存在而不是它的价值?
rvighne '16

61

//find first element with "someAttr" attribute
document.querySelector('[someAttr]')

要么

//find all elements with "someAttr" attribute
document.querySelectorAll('[someAttr]') 

按属性查找元素。现在所有相关浏览器(甚至是IE8)都支持它:http : //caniuse.com/#search=queryselector


2
当问题明确要求:“我需要至少在IE7中有效的本机解决方案 ”时,这怎么会有这么多的反对意见。其次,该链接指出,即使它实际上是从IE8开始的,支持也从IE11开始-也许应该将其交换到developer.mozilla.org/en-US/docs/Web/API/Element/…以便它实际上支持答案。 ..?
Zze

7
所有投票的原因以及我做出回答的原因是,这个SO问题确实很老,因此,当您搜索如何查找DOM元素时,您会在搜索结果中发现这个问题,因为这就是人们正在寻找他们的支持。有用性>历史准确性。其次,链接仍然可以正常工作,只是caniuse.com隐藏了旧的浏览器,如果您切换到“ Usage relative”,您仍然会看到旧的浏览器。
Pylinux

工作完美。快速简便
Dawson B

现在是2020年。这应该是现在公认的答案。
NearHuscarl

44

我玩了一下,最终得到了这个简单的解决方案:

function getElementsByAttribute(attribute, context) {
  var nodeList = (context || document).getElementsByTagName('*');
  var nodeArray = [];
  var iterator = 0;
  var node = null;

  while (node = nodeList[iterator++]) {
    if (node.hasAttribute(attribute)) nodeArray.push(node);
  }

  return nodeArray;
}

用法非常简单,甚至可以在IE8中使用:

getElementsByAttribute('data-foo');
// or with parentNode
getElementsByAttribute('data-foo', document);

http://fiddle.jshell.net/9xaxf6jr/

但我建议为此使用querySelector/ All(并且为了支持较旧的浏览器,请使用polyfill):

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

是的,对于querySelectorAll +1。快速的jsperf测试jsperf.com/custom-vs-selectorall-attributes显示,它比接受的答案要快得多...不幸的是,它与IE 7不兼容:(
Sebastien Daniel

11

试试这个工作

document.querySelector('[attribute =“ value”]')

例如:

document.querySelector('[role="button"]')

5

这也可行:

document.querySelector([attribute="value"]);

所以:

document.querySelector([data-foo="bar"]);

2
这缺少实际的querySelector中的单引号。应该是: document.querySelector('[data-foo="bar"]');
Brettins

1

试试这个-我稍微改变了上面的答案:

var getAttributes = function(attribute) {
    var allElements = document.getElementsByTagName('*'),
        allElementsLen = allElements.length,
        curElement,
        i,
        results = [];

    for(i = 0; i < allElementsLen; i += 1) {
        curElement = allElements[i];

        if(curElement.getAttribute(attribute)) {
            results.push(curElement);
        }
    }

    return results;
};

然后,

getAttributes('data-foo');

3
您更改了什么,为什么?
Artjom B. 2015年

1

对@kevinfahy的answer进行一些修改,以允许在需要时按值获取属性:

function getElementsByAttributeValue(attribute, value){
  var matchingElements = [];
  var allElements = document.getElementsByTagName('*');
  for (var i = 0, n = allElements.length; i < n; i++) {
    if (allElements[i].getAttribute(attribute) !== null) {
      if (!value || allElements[i].getAttribute(attribute) == value)
        matchingElements.push(allElements[i]);
    }
  }
  return matchingElements;
}

0

不要在浏览器中使用

在浏览器中,使用document.querySelect('[attribute-name]')

但是,如果您正在进行单元测试,并且模拟的dom具有flakey querySelector实现,则可以解决问题。

这是@kevinfahy的答案,只是使用ES6粗箭头功能进行了精简,并可能以可读性为代价将HtmlCollection转换为数组。

因此,仅适用于ES6编译器。另外,我不确定许多元素的效果如何。

function getElementsWithAttribute(attribute) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) !== null);
}

这是一个变体,它将获得具有特定值的属性

function getElementsWithAttributeValue(attribute, value) {
  return [].slice.call(document.getElementsByTagName('*'))
    .filter(elem => elem.getAttribute(attribute) === value);
}
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.