querySelectorAll для сгруппированных атрибутов данных - PullRequest
0 голосов
/ 10 июня 2018

Предположим, у меня есть следующая разметка ...

<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 голосов
/ 10 июня 2018

Нет встроенного селектора для такой вещи, но вы все равно можете сделать это достаточно легко, выбрав все элементы и затем отфильтровав те, которые имеют атрибут, начинающийся с data-namespace:

console.log(
  [...document.querySelectorAll('*')]
    .filter(({ attributes }) =>
      [...attributes].some(({ name }) => name.startsWith('data-namespace'))
    )
);
<div data-baz="baz"></div>
<div data-namespace-title="foo"></div>
<div data-namespace-description="bar"></div>
<div data-namespace-button="foo"></div>
0 голосов
/ 10 июня 2018

Не уверен, что вы захотите изменить формат своих атрибутов, но если вы захотите использовать 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>
0 голосов
/ 10 июня 2018

Нет простого способа сделать это просто потому, что в браузере не реализованы подстановочные селекторы для имени / ключа атрибута (только для его значения).Что вы можете сделать, это просто выполнить итерацию по вашему набору элементов (в этом случае их общий знаменатель равен div), а затем отфильтровать их.

Вы можете получить доступ к списку атрибутов каждого узла DOM с помощьювызов <Node>.attributes, а затем преобразование этого в массив и проверка, соответствует ли один или несколько name каждого атрибута шаблону регулярных выражений /^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);
<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>

Обновление: если вы знакомы с ES6, он станет намного чище, потому что:

  • Мы можемиспользуйте Array.from вместо громоздких Array.prototype.slice.call(...).Совет: вы также можете использовать оператор распространения, то есть const els = [...document.querySelectorAll("div")].
  • . Мы можем использовать Array.some вместо того, чтобы вручную создавать цикл 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);
<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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...