Отримайте список атрибутів data- * за допомогою JavaScript / jQuery


150

З огляду на довільний HTML-елемент з нульовим або більше data-*атрибутами, як можна отримати список пар ключових значень для даних.

Наприклад, з огляду на це:

<div id='prod' data-id='10' data-cat='toy' data-cid='42'>blah</div>

Я хотів би мати можливість цього програмно відновити:

{ "id":10, "cat":"toy", "cid":42 }

Використовуючи jQuery (v1.4.3), отримати доступ до окремих бітів даних $.data()просто, якщо ключі відомі заздалегідь, але не очевидно, як це можна зробити з довільними наборами даних.

Я шукаю "просте" рішення jQuery, якщо воно існує, але я не заперечую проти підходу нижчого рівня в іншому випадку. Я намагався розібратися, $('#prod').attributesале моя відсутність javascript-фу мене підводить.

оновлення

customdata робить те, що мені потрібно. Однак включення модуля jQuery лише за частину його функціональності здавалося надмірним.

Ейболлінг джерела допоміг мені виправити власний код (і покращив мій JavaScript-фу).

Ось таке рішення, яке я придумав:

function getDataAttributes(node) {
    var d = {}, 
        re_dataAttr = /^data\-(.+)$/;

    $.each(node.get(0).attributes, function(index, attr) {
        if (re_dataAttr.test(attr.nodeName)) {
            var key = attr.nodeName.match(re_dataAttr)[1];
            d[key] = attr.nodeValue;
        }
    });

    return d;
}

оновлення 2

Як показано у прийнятій відповіді, рішення тривіальне за допомогою jQuery (> = 1.4.4). $('#prod').data()поверне необхідний диктант даних.


Додаючи "оновлення 2", пам'ятайте про дані jquery (), використовуйте деякий внутрішній кеш, а дані (ключ, значення) не поширюються на DOM, що може спричинити багато головних болів. Крім того, оскільки дані jquery 3 () перетворять атрибут data-some-thing = "test" в {someThing: "test"}
ETNyx

Відповіді:


96

Насправді, якщо ви працюєте з jQuery, як у версії 1.4.31.4.4 (через помилку, про яку йдеться у коментарях нижче), data-*атрибути підтримуються через .data():

Станом на jQuery 1.4.3 data- атрибути HTML 5 автоматично включаються до об'єкта даних jQuery.

Зауважте, що рядки залишаються недоторканими, тоді як значення JavaScript перетворюються на пов'язане з ними значення (сюди входять булеви, числа, об'єкти, масиви та нуль). Ці data- атрибути втягуються в перший раз властивість даних , доступ і потім більше не доступні або мутантним (всі значення даних потім зберігаються всередині JQuery).

jQuery.fn.dataФункція повертає всі data-атрибута всередині об'єкта в вигляді пар ключ-значення, причому ключ є частиною імені атрибута після того, як data-і значення є значенням цього атрибуту після перетворення в відповідно до правил , викладеними вище.

Я також створив просту демонстраційну версію, якщо це не переконує вас: http://jsfiddle.net/yijiang/WVfSg/


3
Ні, це порушено в 1.4.3 . Явно потрібно не менше 1.4.4.
Півмісяць свіжий

Дякую. Саме це я і шукав. Я раніше спробував це з 1.4.3 і не зайшов дуже далеко. Демонстрація jsfiddle також допомогла.
Шон Чін

2
@Isc: одна річ , яка дуже дратує спроба Jquery за адресою «десеріалізациі» значенням , знайденим в атрибуті (тобто від майстра : !jQuery.isNaN( data ) ? parseFloat( data ) : ...). У моєму атрибуті були серійні номери продуктів, такі як data-serial="00071134"jQuery перетворився на номер 71134, що змусило мене повернутися до менш елегантного .attr('data-serial')(не варіант у вашому випадку). Я бачив запитання щодо ТА, які озвучують подібні розчарування wrt .data(), спробують викопати одне ...
Crescent Fresh

@CrescentFresh: Добрий момент. Однозначно те, на що я повинен стежити. У своєму рішенні ( gist.github.com/701652 ) я повертаюся до розбору node.attributes, коли jQuery <1.4.3; маючи на увазі це питання, можливо, я повинен просто дотримуватися ручного розбору атрибутів.
Шон Чін

7
Майте на увазі, що $.data()також повертає все, що ви зберігали $.data(key, value). Якщо ви дійсно хочете перевірити, чи дійсно щось зберігається в розмітці як атрибут data- *, цей метод може виявитися не найкращим вибором.
Філіп Уолтон

81

Також слід запропонувати чисте рішення JavaScript, оскільки рішення не є складним:

var a = [].filter.call(el.attributes, function(at) { return /^data-/.test(at.name); });

Це дає масив об’єктів атрибутів, які мають nameта valueвластивості:

if (a.length) {
    var firstAttributeName = a[0].name;
    var firstAttributeValue = a[0].value;
}

Редагування: Щоб зробити крок далі, ви можете отримати словник, повторивши атрибути та заповнивши об’єкт даних:

var data = {};
[].forEach.call(el.attributes, function(attr) {
    if (/^data-/.test(attr.name)) {
        var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
            return $1.toUpperCase();
        });
        data[camelCaseName] = attr.value;
    }
});

Потім ви можете отримати доступ до значення, наприклад, data-my-value="2"як data.myValue;

jsfiddle.net/3KFYf/33

Редагувати: Якщо ви хочете встановити атрибути даних на своєму елементі програмно з об'єкта, ви можете:

Object.keys(data).forEach(function(key) {
    var attrName = "data-" + key.replace(/[A-Z]/g, function($0) {
        return "-" + $0.toLowerCase();
    });
    el.setAttribute(attrName, data[key]);
});

jsfiddle.net/3KFYf/34

EDIT: Якщо ви використовуєте babel або TypeScript або кодуєте лише для браузерів es6, це хороше місце для використання функцій стрілок es6 та трохи скоротити код:

var a = [].filter.call(el.attributes, at => /^data-/.test(at.name));

Хороша відповідь! Перший рядок не замінює такий -символ, як jQuery, але відредагований відповідь.
Тімо Хуовінен

@ gilly3 Схоже, ваша jsfiddle не працює. Ви можете подивитися?
Етан

1
@Ethan - виправлено. Дякую що дали мені знати. Я використовував beautify.js від jsbeautifier.org для гарного друку JSON. Мабуть, це посилання зараз порушено. Але це було зайвим, оскільки JSON.stringify()вбудовано форматування JSON.
gilly3

@ gilly3 Фантастично, ваша рутина чудова для всіх. Було б легко додати дані для отримання даного ключа, а також оновити змінені дані для ключів? Якщо ви можете поділитися, це було б чудово.
Етан

@Ethan - Для отримання одного значення, overthink його: el.getAttribute("data-foo"). Я оновив свою відповідь, щоб показати, як можна встановлювати атрибути даних на основі об'єкта.
gilly3

22

Подивіться тут :

Якщо браузер також підтримує API JavaScript HTML5, ви маєте змогу отримати дані за допомогою:

var attributes = element.dataset

або

var cat = element.dataset.cat

О, але я також читав:

На жаль, нова властивість набору даних ще не була реалізована в жодному браузері, тому тим часом найкраще використовувати getAttributeта setAttributeяк було показано раніше.

Це з травня 2010 року.


Якщо ви користуєтеся jQuery так чи інакше, ви, можливо, захочете ознайомитися з плагіном customdata . Я не маю досвіду з цим, хоча.


Крім того , інтерес, від ППК: quirksmode.org/dom/w3c_core.html#attributes
загострений

Дякую Фелікс Я натрапив на користувацькі дані. На жаль, він не робить те, що мені потрібно - тобто отримує всі дані, враховуючи, що ключі невідомі заздалегідь.
Шон Чін

@lsc: У документації написано, що це $("#my").customdata()повинно дати вам {method: "delete", remote: "true"}... так воно має працювати.
Фелікс Клінг

Використання окремого плагіна jQuery здається зайвим, але перегляд джерела користувальницьких даних допоміг мені виправити власні рішення! Прийме вашу відповідь та оновить Q робочою функцією.
Шон Чин

1
@lsc: Цілком добре, вкладення рішень завжди слід віддавати перевагу imo. На жаль, я не в курсі останніх розробок jQuery;) Просто цікаво, чому хтось проголосував за мене ...
Фелікс Клінг

5

Як було сказано вище, сучасні браузери мають API HTMLElement.dataset .
Цей API дає вам DOMStringMap , і ви можете отримати список data-*атрибутів, просто виконуючи такі дії:

var dataset = el.dataset; // as you asked in the question

Ви також можете отримати масив з такими data-ключовими іменами властивості, як

var data = Object.keys(el.dataset);

або зіставити його значення за

Object.keys(el.dataset).map(function(key){ return el.dataset[key];});
// or the ES6 way: Object.keys(el.dataset).map(key=>{ return el.dataset[key];});

і подібне до цього, ви можете перебирати їх і використовувати їх без необхідності фільтрувати між усіма атрибутами елемента, як це потрібно було робити раніше .


3

або перетворити gilly3відмінну відповідь на метод jQuery:

$.fn.info = function () {
    var data = {};
    [].forEach.call(this.get(0).attributes, function (attr) {
        if (/^data-/.test(attr.name)) {
            var camelCaseName = attr.name.substr(5).replace(/-(.)/g, function ($0, $1) {
                return $1.toUpperCase();
            });
            data[camelCaseName] = attr.value;
        }
    });
    return data;
}

Використання $('.foo').info():;


2

Вам слід отримати дані за допомогою атрибутів набору даних

var data = element.dataset;

Набір даних є корисним інструментом для отримання даних-атрибута


IIRC, this.datasetпоки не працює у всіх браузерах. Однак існує плагін jquery, який забезпечує цю функцію.
Шон Чін

1

Ви можете просто повторити атрибути даних, як і будь-який інший об’єкт, щоб отримати ключі та значення, ось як це зробити з $.each:

    $.each($('#myEl').data(), function(key, value) {
        console.log(key);
        console.log(value);
    });

1

Я використовую кожне вкладене - для мене це найпростіше рішення (Легко керувати / змінювати "те, що ви робите зі значеннями - у моєму прикладі виводяться дані-атрибути як ul-list) (Jquery Code)

var model = $(".model");

var ul = $("<ul>").appendTo("body");

$(model).each(function(index, item) {
  ul.append($(document.createElement("li")).text($(this).text()));
  $.each($(this).data(), function(key, value) {
    ul.append($(document.createElement("strong")).text(key + ": " + value));
    ul.append($(document.createElement("br")));
  }); //inner each
  ul.append($(document.createElement("hr")));
}); // outer each

/*print html*/
var htmlString = $("ul").html();
$("code").text(htmlString);
<script src="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/prism.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.17.1/themes/prism-okaidia.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<h1 id="demo"></h1>

<ul>
  <li class="model" data-price="45$" data-location="Italy" data-id="1234">Model 1</li>
  <li class="model" data-price="75$" data-location="Israel" data-id="4321">Model 2</li> 
  <li class="model" data-price="99$" data-location="France" data-id="1212">Model 3</li> 
</ul>

<pre>
<code class="language-html">
  
</code>
</pre>

<h2>Generate list by code</h2>
<br>

Codepen: https://codepen.io/ezra_siton/pen/GRgRwNw?editors=1111


0

Одним із способів пошуку всіх атрибутів даних є використання element.attributes. Використовуючи .attributes, ви можете переглядати всі атрибути елементів, фільтруючи елементи, які містять рядок "дані-".

let element = document.getElementById("element");

function getDataAttributes(element){
    let elementAttributes = {},
        i = 0;

    while(i < element.attributes.length){
        if(element.attributes[i].name.includes("data-")){
            elementAttributes[element.attributes[i].name] = element.attributes[i].value
        }
        i++;
    }

    return elementAttributes;

}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.