Dữ liệu jQuery vs Attr?


513

Sự khác biệt trong cách sử dụng giữa $.data$.attrkhi sử dụngdata-someAttribute gì?

Hiểu biết của tôi là $.datađược lưu trữ trong jQuery $.cache, không phải DOM. Do đó, nếu tôi muốn sử dụng $.cacheđể lưu trữ dữ liệu, tôi nên sử dụng $.data. Nếu tôi muốn thêm thuộc tính dữ liệu HTML5, tôi nên sử dụng $.attr("data-attribute", "myCoolValue").



14
@zzz Ngoại trừ việc nó dường như không thực sự trả lời câu hỏi ...?
sdleihssirhc

2
Trên thực tế, nó gián tiếp. Việc gắn một đối tượng thông qua attr()có thể dẫn đến rò rỉ bộ nhớ (ít nhất là trong IE), trong khi sử dụng data()là an toàn. Anh ta gợi ý về điều này trong câu trả lời của mình mặc dù anh ta không nói rõ ràng và nói ra. Thông tin thêm về các tài liệu jQuery (xem "Ghi chú bổ sung"): api.jquery.com/attr
ken

6
@ John B, chỉ FYI (mặc dù điều này đã cũ), thuộc tính dữ liệu của data-someAttributekhông hợp lệ; theo thông số kỹ thuật, chỉ cho phép viết thường. Bạn sẽ gặp vô số vấn đề kỳ lạ bằng cách sử dụng ký tự viết hoa.
ken

1
@AdrienBe Rất nhiều tài liệu tham khảo dễ dàng tìm thấy qua tìm kiếm, nhưng vì tôi chán, nên bạn vào đây: stackoverflow.com/a/22753630/84473
ken

Câu trả lời:


748

Nếu bạn đang truyền dữ liệu đến một phần tử DOM từ máy chủ, bạn nên đặt dữ liệu trên phần tử:

<a id="foo" data-foo="bar" href="#">foo!</a>

Dữ liệu sau đó có thể được truy cập bằng .data()jQuery:

console.log( $('#foo').data('foo') );
//outputs "bar"

Tuy nhiên, khi bạn lưu trữ dữ liệu trên một nút DOM trong jQuery bằng dữ liệu, các biến được lưu trữ trên đối tượng nút . Điều này là để chứa các đối tượng và tham chiếu phức tạp khi lưu trữ dữ liệu trên phần tử nút vì một thuộc tính sẽ chỉ chứa các giá trị chuỗi.

Tiếp tục ví dụ của tôi từ trên cao:
$('#foo').data('foo', 'baz');

console.log( $('#foo').attr('data-foo') );
//outputs "bar" as the attribute was never changed

console.log( $('#foo').data('foo') );
//outputs "baz" as the value has been updated on the object

Ngoài ra, quy ước đặt tên cho các thuộc tính dữ liệu có một chút "gotcha" ẩn:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('fooBarBaz') );
//outputs "fizz-buzz" as hyphens are automatically camelCase'd

Khóa gạch nối vẫn sẽ hoạt động:

HTML:
<a id="bar" data-foo-bar-baz="fizz-buzz" href="#">fizz buzz!</a>
JS:
console.log( $('#bar').data('foo-bar-baz') );
//still outputs "fizz-buzz"

Tuy nhiên, đối tượng được trả về .data()sẽ không có bộ khóa gạch nối:

$('#bar').data().fooBarBaz; //works
$('#bar').data()['fooBarBaz']; //works
$('#bar').data()['foo-bar-baz']; //does not work

Vì lý do này, tôi khuyên bạn nên tránh khóa gạch nối trong javascript.

Đối với HTML, tiếp tục sử dụng biểu mẫu gạch nối. Thuộc tính HTML đang trù được ASCII-lowercased tự động , vì vậy <div data-foobar></div>, <DIV DATA-FOOBAR></DIV><dIv DaTa-FoObAr></DiV>được coi được đối xử như giống hệt nhau, nhưng đối với khả năng tương thích tốt nhất dưới dạng chữ thường nên được ưa thích.

Các .data() phương pháp cũng sẽ thực hiện một số cơ bản tự động đúc nếu giá trị phù hợp với một mô hình được công nhận:

HTML:
<a id="foo"
    href="#"
    data-str="bar"
    data-bool="true"
    data-num="15"
    data-json='{"fizz":["buzz"]}'>foo!</a>
JS:
$('#foo').data('str');  //`"bar"`
$('#foo').data('bool'); //`true`
$('#foo').data('num');  //`15`
$('#foo').data('json'); //`{fizz:['buzz']}`

Khả năng tự động truyền này rất thuận tiện để khởi tạo các widget & plugin:

$('.widget').each(function () {
    $(this).widget($(this).data());
    //-or-
    $(this).widget($(this).data('widget'));
});

Nếu bạn hoàn toàn phải có giá trị ban đầu dưới dạng chuỗi, thì bạn sẽ cần sử dụng .attr() :

HTML:
<a id="foo" href="#" data-color="ABC123"></a>
<a id="bar" href="#" data-color="654321"></a>
JS:
$('#foo').data('color').length; //6
$('#bar').data('color').length; //undefined, length isn't a property of numbers

$('#foo').attr('data-color').length; //6
$('#bar').attr('data-color').length; //6

Đây là một ví dụ giả định. Để lưu trữ các giá trị màu, tôi đã từng sử dụng ký hiệu hex số (tức là 0xABC123), nhưng đáng chú ý là hex đã được phân tích cú pháp không chính xác trong các phiên bản jQuery trước 1.7.2 và không còn được phân tích cú pháp thành NumberjQuery 1.8 RC 1.

jQuery 1.8 rc 1 đã thay đổi hành vi tự động truyền . Trước đây, bất kỳ định dạng nào là đại diện hợp lệ của một Numbersẽ được chuyển sang Number. Bây giờ, các giá trị là số chỉ được tự động truyền nếu biểu diễn của chúng giữ nguyên. Điều này được minh họa tốt nhất với một ví dụ.

HTML:
<a id="foo"
    href="#"
    data-int="1000"
    data-decimal="1000.00"
    data-scientific="1e3"
    data-hex="0x03e8">foo!</a>
JS:
                              // pre 1.8    post 1.8
$('#foo').data('int');        //    1000        1000
$('#foo').data('decimal');    //    1000   "1000.00"
$('#foo').data('scientific'); //    1000       "1e3"
$('#foo').data('hex');        //    1000     "0x03e8"

Nếu bạn có kế hoạch sử dụng các cú pháp số thay thế để truy cập các giá trị số, hãy đảm bảo truyền giá trị lên Numberđầu tiên, chẳng hạn như với một đơn vị+ .

JS (tiếp):
+$('#foo').data('hex'); // 1000

17
@vitorbal, trong khi điều này là đúng, đối tượng được trả về .data()sẽ không có bộ biểu mẫu gạch nối, vì vậy $('#bar').data('foo-bar-baz')sẽ hoạt động, nhưng $('#bar').data()['foo-bar-baz']sẽ không. Vì lý do này mà tôi đề nghị mọi người tránh sử dụng mẫu gạch nối.
zzzzBov

1
ok, bây giờ tôi hiểu ý của bạn Không biết về chi tiết nhỏ đó, cảm ơn vì đã cập nhật :)
vitorbal

1
@SableFoste, liên kết nào? api.jquery.com/data là liên kết chính xác cho phương thức và không thay đổi theo như tôi biết.
zzzzBov

1
tôi thích, foo, bar, baz, fizz, buzz thêm: D
Usman Younas

1
Yêu từng dòng.
Foo Bar

108

Sự khác biệt chính giữa hai là nơi nó được lưu trữ và cách nó được truy cập.

$.fn.attr lưu trữ thông tin trực tiếp trên phần tử trong các thuộc tính hiển thị công khai khi kiểm tra và cũng có sẵn từ API gốc của phần tử.

$.fn.datalưu trữ thông tin ở một nơi tối nghĩa lố bịch . Nó nằm trong một biến đóng trên địa phương gọi làdata_user là một thể hiện của dữ liệu hàm được xác định cục bộ. Biến này không thể truy cập trực tiếp từ bên ngoài jQuery.

Tập dữ liệu với attr()

  • có thể truy cập từ $(element).attr('data-name')
  • có thể truy cập từ element.getAttribute('data-name'),
  • nếu giá trị là theo hình thức data-namecũng thể truy cập từ $(element).data(name)element.dataset['name']element.dataset.name
  • hiển thị trên phần tử khi kiểm tra
  • không thể là đối tượng

Tập dữ liệu với .data()

  • chỉ có thể truy cập từ.data(name)
  • không thể truy cập từ .attr()hoặc bất cứ nơi nào khác
  • không hiển thị công khai trên phần tử khi kiểm tra
  • có thể là đồ vật

2
Vâng, câu hỏi chính của tôi là nơi dữ liệu này được lưu trữ, vì vậy cảm ơn thông tin đó!
Max Wilder

2
Cũng .attr()là cách để đi, nếu sau đó bạn muốn sử dụng dữ liệu làm bộ chọn (.data() sẽ không được tìm thấy; xem codepen.io/anon/pen/EvawPV?editors=1011 )
Kamafeather

1

Bạn có thể sử dụng data-*thuộc tính để nhúng dữ liệu tùy chỉnh. Các data-*thuộc tính cho chúng ta khả năng nhúng các thuộc tính dữ liệu tùy chỉnh trên tất cả các thành phần HTML.

jQuery .data()Phương thức cho phép bạn lấy / đặt dữ liệu thuộc bất kỳ loại nào thành các phần tử DOM theo cách an toàn khỏi các tham chiếu vòng tròn và do đó không bị rò rỉ bộ nhớ.

.attr()Phương thức jQuery giá trị thuộc tính get / set chỉ cho phần tử đầu tiên trong tập hợp khớp.

Thí dụ:

<span id="test" title="foo" data-kind="primary">foo</span>

$("#test").attr("title");
$("#test").attr("data-kind");
$("#test").data("kind");
$("#test").data("value", "bar");
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.