Nhận danh sách các thuộc tính data- * bằng cách sử dụng javascript / jQuery


150

Đưa ra một phần tử HTML tùy ý có 0 hoặc nhiều data-*thuộc tính, làm thế nào người ta có thể truy xuất danh sách các cặp khóa-giá trị cho dữ liệu.

Ví dụ:

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

Tôi muốn có thể lấy lập trình này:

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

Sử dụng jQuery (v1.4.3), việc truy cập các bit dữ liệu riêng lẻ bằng cách sử dụng $.data()rất đơn giản nếu các khóa được biết trước, nhưng không rõ ràng làm thế nào người ta có thể làm như vậy với các bộ dữ liệu tùy ý.

Tôi đang tìm kiếm một giải pháp jQuery 'đơn giản' nếu có, nhưng sẽ không bận tâm đến cách tiếp cận cấp thấp hơn. Tôi đã cố gắng phân tích cú pháp $('#prod').attributesnhưng sự thiếu javascript-fu của tôi đang làm tôi thất vọng.

cập nhật

customdata làm những gì tôi cần. Tuy nhiên, bao gồm một plugin jQuery chỉ cho một phần chức năng của nó có vẻ như quá mức cần thiết.

Nhãn cầu nguồn giúp tôi sửa mã của riêng mình (và cải thiện javascript-fu).

Đây là giải pháp tôi đã đưa ra:

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;
}

cập nhật 2

Như đã trình bày trong câu trả lời được chấp nhận, giải pháp này không quan trọng bằng jQuery (> = 1.4.4). $('#prod').data()sẽ trả về dict dữ liệu cần thiết.


Thêm "cập nhật 2" lưu ý đến dữ liệu jquery () sử dụng một số bộ đệm trong và dữ liệu (khóa, giá trị) không truyền đến DOM, điều này có thể gây ra nhiều vấn đề đau đầu. Ngoài ra, kể từ khi jquery 3 data () chuyển đổi data-some-thing = "test" thành {someThing: "test"}
ETNyx 11/07/19

Câu trả lời:


96

Thực tế, nếu bạn đang làm việc với jQuery, như phiên bản 1.4.31.4.4 (do lỗi như được đề cập trong các bình luận bên dưới), data-*các thuộc tính được hỗ trợ thông qua .data():

Kể từ jQuery 1.4.3, data- các thuộc tính HTML 5 sẽ được tự động kéo vào đối tượng dữ liệu của jQuery.

Lưu ý rằng các chuỗi được giữ nguyên trong khi các giá trị JavaScript được chuyển đổi thành giá trị được liên kết của chúng (điều này bao gồm booleans, số, đối tượng, mảng và null). Các data- thuộc tính được kéo trong lần đầu tiên thuộc tính dữ liệu được truy cập và sau đó không còn được truy cập hoặc bị thay đổi (tất cả các giá trị dữ liệu sau đó được lưu trữ nội bộ trong jQuery).

Các jQuery.fn.datachức năng sẽ trở lại tất cả các data-thuộc tính bên trong một đối tượng như cặp khóa-giá trị, với chìa khóa là một phần của tên thuộc tính sau data-và giá trị là giá trị của thuộc tính rằng sau khi được chuyển đổi theo các quy tắc đã nêu ở trên.

Tôi cũng đã tạo một bản demo đơn giản nếu điều đó không thuyết phục bạn: http://jsfiddle.net/yijiang/WVfSg/


3
Không, điều này bị hỏng trong 1.4.3 . Tối thiểu 1.4.4 là bắt buộc rõ ràng.
Lưỡi liềm tươi

Cảm ơn. Đó chính xác là những gì tôi đang tìm kiếm. Trước đây tôi đã thử điều đó với 1.4.3 và không đi quá xa. jsfiddle demo đã giúp quá.
Shawn Chin

2
@Isc: một điều đó là rất khó chịu là nỗ lực của jQuery tại "deserializing" giá trị được tìm thấy trong các thuộc tính (tức là từ thạc sĩ : !jQuery.isNaN( data ) ? parseFloat( data ) : ...). Tôi đã có các số sê-ri sản phẩm trong thuộc tính của mình, chẳng hạn như data-serial="00071134"jQuery đã nhập vào một số 71134, buộc tôi phải trở lại trạng thái kém thanh lịch .attr('data-serial')(không phải là một tùy chọn trong trường hợp của bạn). Tôi đã thấy những câu hỏi về SO đã lên tiếng về sự thất vọng tương tự .data(), sẽ cố gắng khai thác ...
Crescent Fresh

@CrescentFresh: Điểm tốt. Chắc chắn một cái gì đó tôi nên coi chừng. Trong giải pháp của tôi ( gist.github.com/701652 ) tôi quay lại phân tích cú pháp node.attribution khi jQuery <1.4.3; với vấn đề này, có lẽ tôi chỉ nên sử dụng phân tích cú pháp các thuộc tính theo cách thủ công.
Shawn Chin

7
Hãy nhớ rằng $.data()cũng trả lại bất cứ thứ gì bạn đã lưu trữ bằng cách sử dụng $.data(key, value). Nếu bạn thực sự muốn kiểm tra xem một cái gì đó thực sự được lưu trữ trong đánh dấu dưới dạng một thuộc tính data- *, phương pháp này có thể không phải là lựa chọn tốt nhất.
Philip Walton

81

Một giải pháp JavaScript thuần túy cũng nên được cung cấp, vì giải pháp không khó:

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

Điều này cung cấp một mảng các đối tượng thuộc tính, có namevaluethuộc tính:

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

Chỉnh sửa: Để tiến thêm một bước, bạn có thể lấy từ điển bằng cách lặp lại các thuộc tính và điền vào một đối tượng dữ liệu:

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;
    }
});

Sau đó, bạn có thể truy cập giá trị của, ví dụ, data-my-value="2"như data.myValue;

jsfiddle.net/3KFYf/33

Chỉnh sửa: Nếu bạn muốn đặt thuộc tính dữ liệu trên phần tử của mình theo chương trình từ một đối tượng, bạn có thể:

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 432

EDIT: Nếu bạn đang sử dụng babel hoặc TypeScript, hoặc chỉ mã hóa cho các trình duyệt es6, đây là một nơi tuyệt vời để sử dụng các hàm mũi tên es6 và rút ngắn mã một chút:

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

Câu trả lời tốt! Dòng đầu tiên không thay thế -ký tự như jQuery nhưng câu trả lời đã chỉnh sửa.
Timo Huovinen

@ gilly3 jsfiddle của bạn dường như không hoạt động. Bạn có thể có một cái nhìn?
Ethan

1
@Ethan - Đã sửa. Cảm ơn vì đã cho tôi biết. Tôi đã sử dụng beautify.js từ jsbeautifier.org để in JSON. Rõ ràng liên kết đó bị hỏng bây giờ. Nhưng, đó là quá mức cần thiết vì JSON.stringify()đã có định dạng JSON được tích hợp.
gilly3

@ gilly3 Tuyệt vời, thói quen của bạn là tuyệt vời để lấy tất cả. Có thể dễ dàng thêm dữ liệu tìm nạp cho một khóa nhất định cũng như cập nhật dữ liệu đã sửa đổi cho (các) khóa không? Nếu bạn có thể chia sẻ, đó sẽ là tuyệt vời.
Ethan

@Ethan - Để nhận một giá trị duy nhất, đừng lật đổ nó : el.getAttribute("data-foo"). Tôi đã cập nhật câu trả lời của mình để cho thấy cách bạn có thể đặt thuộc tính dữ liệu dựa trên một đối tượng.
gilly3

22

Có một cái nhìn ở đây :

Nếu trình duyệt cũng hỗ trợ API JavaScript HTML5, bạn sẽ có thể lấy dữ liệu bằng:

var attributes = element.dataset

hoặc là

var cat = element.dataset.cat

Ồ, nhưng tôi cũng đọc:

Thật không may, thuộc tính bộ dữ liệu mới chưa được triển khai trong bất kỳ trình duyệt nào, vì vậy trong thời gian đó, tốt nhất nên sử dụng getAttributesetAttributenhư đã trình bày trước đó.

Đó là từ tháng 5 năm 2010.


Nếu bạn vẫn sử dụng jQuery, bạn có thể muốn xem qua plugin customdata . Tôi không có kinh nghiệm với nó mặc dù.


Cũng được quan tâm, từ ppk: quirksmode.org/dom/w3c_core.html#attribut
Pointy

Cảm ơn bạn. Tôi đã đi qua customdata. Thật không may, nó không làm những gì tôi cần - tức là lấy tất cả dữ liệu được cung cấp mà các khóa không được biết trước.
Shawn Chin

@lsc: Tài liệu nói rằng $("#my").customdata()sẽ cung cấp cho bạn {method: "delete", remote: "true"}... vì vậy nó sẽ hoạt động.
Felix Kling

Sử dụng một plugin jQuery riêng có vẻ như quá mức cần thiết, nhưng nhìn vào nguồn cho customdata đã giúp tôi khắc phục các giải pháp của riêng mình! Sẽ chấp nhận câu trả lời của bạn và cập nhật Q với chức năng làm việc.
Shawn Chin

1
@lsc: Hoàn toàn tốt, xây dựng trong các giải pháp nên luôn luôn được ưu tiên imo. Thật không may, tôi không cập nhật với sự phát triển mới nhất của jQuery;) Chỉ tự hỏi tại sao ai đó bỏ phiếu cho tôi ...
Felix Kling

5

Như đã đề cập ở trên, các trình duyệt hiện đại có API HTMLEuity.dataset .
API đó cung cấp cho bạn một DOMStringMap và bạn có thể truy xuất danh sách các data-*thuộc tính chỉ cần thực hiện:

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

bạn cũng có thể truy xuất một mảng với các data-tên chính của thuộc tính như

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

hoặc ánh xạ các giá trị của nó bằng cách

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

và như thế này, bạn có thể lặp lại chúng và sử dụng chúng mà không cần phải lọc giữa tất cả các thuộc tính của phần tử như chúng ta cần làm trước đây .


3

hoặc chuyển đổi gilly3câu trả lời tuyệt vời của phương thức 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;
}

Sử dụng : $('.foo').info();


2

Bạn sẽ nhận được dữ liệu thông qua các thuộc tính dữ liệu

var data = element.dataset;

tập dữ liệu là công cụ hữu ích để lấy thuộc tính dữ liệu


IIRC, this.datasetchưa hoạt động trên tất cả các trình duyệt. Tuy nhiên, có một plugin jquery cung cấp tính năng này.
Shawn Chin

1

Bạn chỉ có thể lặp lại các thuộc tính dữ liệu như bất kỳ đối tượng nào khác để nhận khóa và giá trị, đây là cách thực hiện với $.each:

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

1

Tôi sử dụng từng cái lồng nhau - đối với tôi đây là giải pháp đơn giản nhất (Dễ kiểm soát / thay đổi "những gì bạn làm với các giá trị - trong ví dụ đầu ra thuộc tính dữ liệu của tôi là ul-list) (Mã Jquery)

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

Một cách để tìm tất cả các thuộc tính dữ liệu là sử dụng element.attributes. Sử dụng .attributes, bạn có thể lặp qua tất cả các thuộc tính thành phần, lọc ra các mục bao gồm chuỗi "data-".

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;

}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.