Как найти элемент, основанный на значении атрибута данных?


994

У меня есть следующий сценарий:

var el = 'li';

и <li>на странице 5 с data-slide=numberатрибутом (число 1,2,3,4,5 соответственно) .

Теперь мне нужно найти номер текущего активного слайда, который отображается var current = $('ul').data(current);и обновляется при каждой смене слайдов.

До сих пор мои попытки не увенчались успехом, пытаясь создать селектор, который бы соответствовал текущему слайду:

$('ul').find(el+[data-slide=+current+]);

не соответствует / не возвращает ничего ...

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

Есть идеи о том, что мне не хватает?


6
Вы уверены, что в вашем .find(el+[data-slide=+current+]);коде вы пишете? кажется, вы пропустили некоторые цитаты"[data-slide]"
xandy

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

Ответы:


1481

Вы должны ввести значение currentв селектор Attribute Equals :

$("ul").find(`[data-slide='${current}']`)

Для более старых сред JavaScript ( ES5 и более ранних):

$("ul").find("[data-slide='" + current + "']"); 

8
@ Яннис, ты мог бы сделать $("ul").find(el + "[data-slide='" + current +"']");.
Фредерик Хамиди

7
@ c00lryguy, пользовательский интерфейс jQuery определяет один, и вокруг него есть отдельные реализации . Похоже, что попытки добавить его в jQuery Core были отклонены . Дважды .
Фредерик Хамиди

6
этот ответ на аналогичный пост имеет пример функции фильтра
drzaus

77
Я беспокоюсь, что это не сработает, если данные были добавлены с помощью функции jQuery .data (...), поскольку это не всегда отображает атрибут, а иногда использует механизм хранения, специфичный для браузера. Еще одна причина, по которой мне бы хотелось, чтобы ядро ​​jQuery имело селектор для конкретных данных.
AaronLS

77
Обратите внимание, что это не работает для элементов, для которых вы устанавливаете данные с помощью $ ('# element'). Data ('some-att-name', value); но только для тех, кто имеет жестко закодированный атрибут. У меня есть эта проблема и заставить его работать с набором данных, написав атрибут напрямую $ ('# element'). Attr ('data-some-att-name', value);
Павел

463

в случае, если вы не хотите вводить все это, вот более короткий способ запроса по атрибуту данных:

$("ul[data-slide='" + current +"']");

К вашему сведению: http://james.padolsey.com/javascript/a-better-data-selector-for-jquery/


31
Для тех из вас, кого это волнует, учитывая структуру, <ul><li data-slide="item"></li></ul>этот селектор ответа вернет неопределенное значение, поэтому он не работает с учетом сценария пользователя. Этот ответ будет работать для структуры. <ul data-slide="item"><li></li></ul> Хотя я понимаю, почему его популярность объясняется краткостью, технически это неправильный ответ. jsfiddle.net/py5p2abL/1
akousmata

4
Не забудьте рассматривать это как массив. Используйте [0]для доступа к первому найденному элементу.
Амина Нурайни

Странный побочный эффект ... этот метод работал, сопоставляя элемент с атрибутом данных, когда .find("[data-attrib='value']")не работал. Я не знаю, были ли значения атрибутами данных добавлены jQuery или нет ...
erroric

1
Это не странно, потому что два ответа делают две разные вещи. $.findв частности, находит потомков этого элемента, но использование синтаксиса фильтра в строке селектора просто отфильтрует результаты.
Фил

227

При поиске с помощью [data-x = ...] обратите внимание: он не работает с установщиком jQuery.data (..) :

$('<b data-x="1">'  ).is('[data-x=1]') // this works
> true

$('<b>').data('x', 1).is('[data-x=1]') // this doesn't
> false

$('<b>').attr('data-x', 1).is('[data-x=1]') // this is the workaround
> true

Вы можете использовать это вместо:

$.fn.filterByData = function(prop, val) {
    return this.filter(
        function() { return $(this).data(prop)==val; }
    );
}

$('<b>').data('x', 1).filterByData('x', 1).length
> 1

1
$.fn.filterByDataявляется блестящим; однако, это предупреждение для тех, кто копирует там ... вам нужно только $('<b>').filterByData('x', 1)найти <b>теги с data-x="1". если вы скопируете и вставите .data(x, 1)часть ... вы будете устанавливать data-x«1» перед фильтрацией.
WEBjuju

39

Я улучшил расширение filterByData от psycho brm до jQuery.

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

(function ($) {

    $.fn.filterByData = function (prop, val) {
        var $self = this;
        if (typeof val === 'undefined') {
            return $self.filter(
                function () { return typeof $(this).data(prop) !== 'undefined'; }
            );
        }
        return $self.filter(
            function () { return $(this).data(prop) == val; }
        );
    };

})(window.jQuery);

Применение:

$('<b>').data('x', 1).filterByData('x', 1).length    // output: 1
$('<b>').data('x', 1).filterByData('x').length       // output: 1

Или скрипка: http://jsfiddle.net/PTqmE/46/


34

Без JQuery, ES6

document.querySelectorAll(`[data-slide='${current}']`);

Я знаю, что вопрос касается JQuery, но читатели могут захотеть использовать чистый метод JS.


33

Я столкнулся с той же проблемой при получении элементов с использованием атрибутов jQuery и data- *.

поэтому для вашей справки самый короткий код здесь:

Это мой HTML-код:

<section data-js="carousel"></section>
<section></section>
<section></section>
<section data-js="carousel"></section>

Это мой селектор jQuery:

$('section[data-js="carousel"]');
// this will return array of the section elements which has data-js="carousel" attribute.


15

Этот селектор $("ul [data-slide='" + current +"']");будет работать для следующей структуры:

<ul><li data-slide="item"></li></ul>  

Пока это $("ul[data-slide='" + current +"']");будет работать для:

<ul data-slide="item"><li></li></ul>


12

Возвращаясь к его первоначальному вопросу о том, как заставить это работать, не зная заранее типа элемента, следующее делает это:

$(ContainerNode).find(el.nodeName + "[data-slide='" + current + "']");
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.