Выбор элемента по атрибуту данных


1020

Существует ли простой и прямой способ выбора элементов на основе их dataатрибута? Например, выберите все якоря с именованным атрибутом данных customerID, значение которого равно 22.

Я не решаюсь использовать relдругие атрибуты для хранения такой информации, но мне гораздо сложнее выбрать элемент на основе того, какие данные в нем хранятся.



Вот что помогло мне выбрать все атрибуты данных (независимо от значения): $('*[data-customerID]')Вы можете использовать его, например, с$('*[data-customerID]').each( function() { ... });
Кай Ноак

Ответы:


1469
$('*[data-customerID="22"]');

Вы должны быть в состоянии опустить *, но если я правильно помню, в зависимости от того, какую версию jQuery вы используете, это может дать ошибочные результаты.

Обратите внимание, что для совместимости с Selectors API ( document.querySelector{,all}), кавычки вокруг значения атрибута ( 22) не могут быть опущены в этом случае .

Кроме того, если вы много работаете с атрибутами данных в своих сценариях jQuery, вы можете рассмотреть возможность использования плагина пользовательских атрибутов данных HTML5 . Это позволяет вам писать еще более читабельный код с помощью .dataAttr('foo')и приводит к уменьшению размера файла после минимизации (по сравнению с использованием .attr('data-foo')).


69
Просто обратите внимание, что .data ('foo') работает, чтобы получить значение атрибута 'data-foo', начиная с jQuery 1.4.3. Кроме того, начиная с jQuery 1.6: .data ('fooBar') получает атрибут 'data-foo-bar'.
Джеймс МакКормак,

4
@Zootius: Да, в readme плагина есть примечание: «Начиная с jQuery 1.4.3, по умолчанию он .data()сопоставляется с пользовательскими data-*атрибутами, что делает этот плагин избыточным. Тем не менее, он все еще может быть использован для более старых версий jQuery ».
Матиас Биненс

Так как же опубликовать jQuery 1.4.3, выбрать объект по значению его объекта данных? Давайте я хотел бы выбрать в этом примере любой объект с данными для customerID, равным 22?
Поездка

54
Также, если вас интересует только наличие определенного атрибута данных, вы можете сделать это:$('[data-customerID]')
Darkside

7
Это не работает, если поле данных было установлено с помощью jquery (используя .data()), верно?
Мартин Р.

330

Для людей, гуглящих и желающих иметь более общие правила выбора при помощи атрибутов данных:

$("[data-test]")выберет любой элемент, который просто имеет атрибут данных (независимо от значения атрибута). Включая:

<div data-test=value>attributes with values</div>
<div data-test>attributes without values</div>

$('[data-test~="foo"]')выберет любой элемент, который содержит атрибут данных, fooно не обязательно должен быть точным, например:

<div data-test="foo">Exact Matches</div>
<div data-test="this has the word foo">Where the Attribute merely contains "foo"</div>

$('[data-test="the_exact_value"]')выберет любой элемент с точным значением атрибута данных the_exact_value, например:

<div data-test="the_exact_value">Exact Matches</div>

но нет

<div data-test="the_exact_value foo">This won't match</div>

21
Хорошо. Обратите внимание, что ~=совпадает с разделенными пробелами словами, тогда как *=соответствует любой подстроке.
Сэм

Как насчет ^характера?
kuba44

1
@ kuba44 на самом деле вы также можете использовать ^, так как $('[data-test^=foo]')в этом случае вы выбираете что-либо, начинающееся с foo, например, <div data-test="foo_exact_value">или <div data-test="food">нет<div data-test="seafoo">
JDuarteDJ

Полный список селекторов атрибутов: drafts.csswg.org/selectors-3/#attribute-selectors
user1460043

142

Использование $('[data-whatever="myvalue"]')выберет что-нибудь с html-атрибутами, но в более новых jQueries кажется, что если вы используете $(...).data(...)для прикрепления данных, он использует некоторую волшебную вещь браузера и не влияет на html, поэтому не обнаруживается, .findкак указано в предыдущем ответе .

Проверьте (протестировано с 1.7.2+) (также см. Скрипту ): (обновлено, чтобы быть более полным)

var $container = $('<div><div id="item1"/><div id="item2"/></div>');

// add html attribute
var $item1 = $('#item1').attr('data-generated', true);

// add as data
var $item2 = $('#item2').data('generated', true);

// create item, add data attribute via jquery
var $item3 = $('<div />', {id: 'item3', data: { generated: 'true' }, text: 'Item 3' });
$container.append($item3);

// create item, "manually" add data attribute
var $item4 = $('<div id="item4" data-generated="true">Item 4</div>');
$container.append($item4);

// only returns $item1 and $item4
var $result = $container.find('[data-generated="true"]');

1
ага - оказывается, кто-то еще указывает на это на stackoverflow.com/questions/4191386/…
drzaus

4
и предлагает решение .filter здесь
drzaus

22
он использует магию браузера и не влияет на html : нет такой вещи, как магия;) learningjquery.com/2011/09/using-jquerys-data-apis
Том Сардуй


1
Если вы добавляете атрибут данных, который вам нужно найти позже, используйте$item.attr('data-id', 10);
Pedro Moreira

78

Я не видел ответа JavaScript без jQuery. Надеюсь, это кому-нибудь поможет.

var elements = document.querySelectorAll('[data-customerID="22"]');

elements[0].innerHTML = 'it worked!';
<a data-customerID='22'>test</a>

Информация:


1
Спасибо за это. Приятно видеть не jquery решения.
Чак

68

Чтобы выбрать все привязки с атрибутом данных data-customerID==22, вы должны включить, aчтобы ограничить область поиска только этим типом элемента. Поиск атрибутов данных в большом цикле или с высокой частотой, когда на странице много элементов, может вызвать проблемы с производительностью.

$('a[data-customerID="22"]');

27

Native JS Примеры

Получить NodeList элементов

var elem = document.querySelectorAll('[data-id="container"]')

HTML: <div data-id="container"></div>

Получить первый элемент

var firstElem = document.querySelector('[id="container"]')

HTML: <div id="container"></div>

Таргетинг на коллекцию узлов, которая возвращает список узлов

document.getElementById('footer').querySelectorAll('[data-id]')

HTML:

<div class="footer">
    <div data-id="12"></div>
    <div data-id="22"></div>
</div>

Получить элементы на основе нескольких (ИЛИ) значений данных

document.querySelectorAll('[data-section="12"],[data-selection="20"]')

HTML:

<div data-selection="20"></div>
<div data-section="12"></div>

Получить элементы на основе комбинированных (И) значений данных

document.querySelectorAll('[data-prop1="12"][data-prop2="20"]')

HTML:

<div data-prop1="12" data-prop2="20"></div>

Получить элементы, где значение начинается с

document.querySelectorAll('[href^="https://"]')

Селектор для «получить первый элемент» правильный, но не согласуется с другими примерами - я полагаю, что отсутствует «data-».
GuyPaddock

15

через метод фильтра Jquery ():

http://jsfiddle.net/9n4e1agn/1/

HTML:

<button   data-id='1'>One</button>
<button   data-id='2'>Two</button>

JavaScript:

$(function() {    
    $('button').filter(function(){
        return $(this).data("id")   == 2}).css({background:'red'});  
     });

Ты пробовал скрипку? Метод FIlter - это просто еще один подход для достижения того же самого. Это может быть полезно, когда у вас уже есть набор объектов Jquery, и вам необходимо выполнить фильтрацию на основе атрибута данных или чего-либо еще.
Разан Пол

Мои извинения, @Blizzard. Я прокомментировал неправильный ответ. Вставил его прямо сейчас. #AlwaysALongDayAtWork
Питер Бишоп

15

Конструкция такая: $('[data-XXX=111]')не работает в Safari 8.0 .

Если вы установили данные объясняют это так: $('div').data('XXX', 111)он работает только если установить атрибут данных непосредственно в DOM так: $('div').attr('data-XXX', 111).

Я думаю, это потому, что команда jQuery оптимизировала сборщик мусора для предотвращения утечек памяти и тяжелых операций при перестроении DOM для каждого атрибута данных изменений.


Это мне очень помогло - если я использовал методы data или prop, тогда выбор по $ ('... [data-x = "y"]') не работал - вместо этого я использовал attr (он выдвигает изменение атрибута на ДОМ). Thx
Jarda

13

Чтобы это работало в Chrome, значение не должно быть другой пары кавычек.

Это работает только, например, так:

$('a[data-customerID=22]');

4
Это кажется неправильным. По крайней мере, сейчас это не правильно. Я только что использовал $ ('[data-action = "setStatus"]'). RemoveClass ('disabled'); в хроме и работает отлично.
Петр епископ

Я полагаю, что в селекторе нет смысла использовать «», его можно использовать как:$('[data-action=setStatus]').removeClass('disabled')
Анимеш Сингх,

6

Иногда желательно фильтровать элементы на основе того, имеют ли они элементы данных, присоединенные к ним программно (иначе как через атрибуты dom):

$el.filter(function(i, x) { return $(x).data('foo-bar'); }).doSomething();

Вышеописанное работает, но не очень читабельно. Лучший подход - использовать псевдоселектор для проверки такого рода вещей:

$.expr[":"].hasData = $.expr.createPseudo(function (arg) {
    return function (domEl) {
        var $el = $(domEl);
        return $el.is("[" + ((arg.startsWith("data-") ? "" : "data-") + arg) + "]") || typeof ($el.data(arg)) !== "undefined";
    };
});

Теперь мы можем изменить исходное утверждение на что-то более свободное и читаемое:

$el.filter(":hasData('foo-bar')").doSomething();

1
Первое решение пропускает оператор return, оно должно быть: $ el.filter (function (i, x) {return $ (x) .data ('foo-bar');}). DoSomething ();
Сальма Гомаа

3

Просто для того, чтобы завершить все ответы некоторыми функциями «жизненного стандарта» - к настоящему моменту (в эпоху html5) это можно сделать без сторонних библиотек:

  • чистый / простой JS с querySelector (использует CSS-селекторы):
    • выберите первое в DOM: document.querySelector('[data-answer="42"],[type="submit"]')
    • выбрать все в DOM: document.querySelectorAll('[data-answer="42"],[type="submit"]')
  • чистый / простой CSS
    • некоторые конкретные теги: [data-answer="42"],[type="submit"]
    • все теги с определенным атрибутом: [data-answer]илиinput[type]
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.