Получить элементы по атрибуту, когда querySelectorAll недоступен без использования библиотек?


124
<p data-foo="bar">

Как вы можете сделать эквивалент

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

где querySelectorAll это не доступно ?

Мне нужно собственное решение, которое работает хотя бы в IE7. Меня не волнует IE6.


ознакомьтесь с библиотекой селекторов javascript sizzle.js
эпоха

1
Хорошо, да, единственное, что мне нужно сделать, это атрибуты данных, поэтому я пытался придумать самый простой способ исправить это, не задействуя весь механизм выбора, такой как Sizzle. Но стоит заглянуть в первоисточник. Кстати, еще один отличный механизм выбора - github.com/ded/qwery
ryanve,

@ryanve, спасибо, посмотрю :)
epoch

Рабочее решение, которое я использовал, находится в github.com/ryanve/dope/blob/master/dope.js в методе под названием 'queryAttr'
ryanve

7
Лол, твой вопрос - это мой ответ. Так что возникает еще один вопрос. В какой ситуации это querySelectorAllнедоступно? note - I don't care all IE
вжень

Ответы:


137

Вы можете написать функцию, которая запускает 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

1
Зачем использовать document.getElementsByTagName('*')вместо document.all?
pedrozath

1
Почему бы не использовать hasAttributeвместо getAttribute() !== null, поскольку вы хотите проверить только наличие, а не его значение?
rvighne

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 ». Во-вторых, в этой ссылке говорится, что поддержка начинается с IE11, хотя на самом деле она начинается с IE8 - возможно, это следует заменить на developer.mozilla.org/en-US/docs/Web/API/Element/…, чтобы он действительно поддерживал ответ. ..?
Zze

7
Причина всех положительных отзывов и причина, по которой я дал ответ, заключается в том, что этот вопрос SO действительно старый, поэтому, когда вы ищете, как найти элементы DOM, вы обнаруживаете, что этот вопрос очень высок в результатах поиска, и поскольку это то, что люди ищем они проголосуют. Полезность> историческая достоверность. Во-вторых, ссылка по-прежнему работает нормально, просто на caniuse.com скрыты старые браузеры, если вы переключитесь на «Относительное использование», вы все равно увидите старые браузеры.
Pylinux

Работает отлично. Быстро и просто
Dawson B

Сейчас 2020 год. Теперь это должен быть принятый ответ.
Рядом с Хускарлом,

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]');

Да, +1 для querySelectorAll. Быстрый тест jsperf jsperf.com/custom-vs-selectorall-attributes показывает, что он намного быстрее, чем принятый ответ ... к сожалению, он не совместим с IE 7 :(
Себастьен Даниэль

11

Попробуйте это работает

document.querySelector ( '[атрибут = "значение"]')

пример :

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.

1

Немного модификация на @kevinfahy «s ответ , чтобы получать атрибут , значение , если это необходимо:

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 есть нестабильная реализация 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);
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.