.prop () so với .attr ()


2301

Vì vậy, jQuery 1.6 có chức năng mới prop().

$(selector).click(function(){
    //instead of:
    this.getAttribute('style');
    //do i use:
    $(this).prop('style');
    //or:
    $(this).attr('style');
})

hoặc trong trường hợp này họ làm điều tương tự?

Và nếu tôi làm phải chuyển sang sử dụng prop(), tất cả các cũ attr()các cuộc gọi sẽ phá vỡ nếu tôi chuyển sang 1.6?

CẬP NHẬT

selector = '#id'

$(selector).click(function() {
    //instead of:
    var getAtt = this.getAttribute('style');
    //do i use:
    var thisProp = $(this).prop('style');
    //or:
    var thisAttr = $(this).attr('style');

    console.log(getAtt, thisProp, thisAttr);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.0/jquery.min.js"></script>
<div id='id' style="color: red;background: orange;">test</div>

(xem thêm câu đố này: http://jsfiddle.net/manenser/JpUF2/ )

Bảng điều khiển ghi nhật ký getAttributedưới dạng chuỗi và attrdưới dạng chuỗi, nhưng proplà a CSSStyleDeclaration, Tại sao? Và làm thế nào điều đó ảnh hưởng đến mã hóa của tôi trong tương lai?


17
Đây sẽ là của xác định lãi suất: books.google.ca/...

28
@Neal, đó là vì sự thay đổi này vượt qua jQuery. Sự khác biệt giữa các thuộc tính HTML và thuộc tính DOM là rất lớn.

7
Tôi cảm thấy buồn khi thấy jQuery hoàn nguyên các thay đổi. Họ đang đi sai hướng.

4
@Neal. Có, và nó chỉ làm phức tạp vấn đề hơn nữa thay vì tách hai phương pháp.

6
@BritishDeveloper câu trả lời phức tạp hơn chỉ đơn giản là luôn luôn sử dụng x hoặc y vì nó phụ thuộc vào những gì bạn định nhận. Bạn có muốn thuộc tính, hoặc bạn muốn tài sản? chúng là hai thứ rất khác nhau.
Kevin B

Câu trả lời:


1876

Cập nhật ngày 1 tháng 11 năm 2012

Câu trả lời ban đầu của tôi áp dụng cụ thể cho jQuery 1.6. Lời khuyên của tôi vẫn giữ nguyên nhưng jQuery 1.6.1 đã thay đổi mọi thứ một chút: khi đối mặt với đống trang web bị hỏng dự đoán, nhóm jQuery đã trở lại attr()một cái gì đó gần với (nhưng không hoàn toàn giống như) hành vi cũ của nó đối với các thuộc tính Boolean . John Resig cũng viết blog về nó . Tôi có thể thấy những khó khăn mà họ gặp phải nhưng vẫn không đồng ý với khuyến nghị của anh ta attr().

Câu trả lời gốc

Nếu bạn chỉ từng sử dụng jQuery và không trực tiếp DOM, đây có thể là một thay đổi khó hiểu, mặc dù đây chắc chắn là một cải tiến về mặt khái niệm. Tuy nhiên, điều này không tốt cho các trang web sử dụng jQuery sẽ bị hỏng do thay đổi này.

Tôi sẽ tóm tắt các vấn đề chính:

  • Bạn thường muốn prop()hơn là attr().
  • Trong phần lớn các trường hợp, prop()làm những gì attr()được sử dụng để làm. Thay thế các cuộc gọi đến attr()bằng prop()mã của bạn thường sẽ hoạt động.
  • Các thuộc tính thường đơn giản để xử lý hơn các thuộc tính. Một giá trị thuộc tính chỉ có thể là một chuỗi trong khi một thuộc tính có thể thuộc bất kỳ loại nào. Ví dụ, thuộc checkedtính là Boolean, thuộc styletính là một đối tượng với các thuộc tính riêng cho mỗi kiểu, thuộc sizetính là một số.
  • Trường hợp cả thuộc tính và thuộc tính có cùng tên tồn tại, thông thường cập nhật cái này sẽ cập nhật cái kia, nhưng đây không phải là trường hợp của một số thuộc tính đầu vào, như valuechecked: đối với các thuộc tính này, thuộc tính luôn đại diện cho trạng thái hiện tại trong khi thuộc tính (ngoại trừ trong các phiên bản cũ của IE) tương ứng với giá trị / độ kiểm tra mặc định của đầu vào (được phản ánh trong defaultValue/ defaultCheckedproperty).
  • Thay đổi này loại bỏ một số lớp ma thuật jQuery bị mắc kẹt trước các thuộc tính và thuộc tính, có nghĩa là các nhà phát triển jQuery sẽ phải tìm hiểu một chút về sự khác biệt giữa các thuộc tính và thuộc tính. Đây là một điều tốt.

Nếu bạn là nhà phát triển jQuery và bị toàn bộ doanh nghiệp này nhầm lẫn về các thuộc tính và thuộc tính, bạn cần lùi lại một bước và tìm hiểu một chút về nó, vì jQuery không còn quá cố gắng để bảo vệ bạn khỏi những thứ này. Đối với từ có thẩm quyền nhưng hơi khô khan về chủ đề này, có các thông số kỹ thuật: DOM4 , HTML DOM , DOM Cấp 2 , DOM Cấp 3 . Tài liệu DOM của Mozilla hợp lệ cho hầu hết các trình duyệt hiện đại và dễ đọc hơn thông số kỹ thuật, vì vậy bạn có thể thấy tài liệu tham khảo DOM của họ hữu ích. Có một phần về thuộc tính yếu tố .

Như một ví dụ về cách các thuộc tính đơn giản để xử lý hơn các thuộc tính, hãy xem xét một hộp kiểm được kiểm tra ban đầu. Đây là hai phần HTML hợp lệ có thể thực hiện việc này:

<input id="cb" type="checkbox" checked>
<input id="cb" type="checkbox" checked="checked">

Vậy, làm thế nào để bạn tìm ra nếu hộp kiểm được kiểm tra với jQuery? Nhìn vào Stack Overflow và bạn thường sẽ tìm thấy các đề xuất sau:

  • if ( $("#cb").attr("checked") === true ) {...}
  • if ( $("#cb").attr("checked") == "checked" ) {...}
  • if ( $("#cb").is(":checked") ) {...}

Đây thực sự là điều đơn giản nhất trên thế giới để làm với thuộc tính checkedBoolean, đã tồn tại và hoạt động hoàn hảo trong mọi trình duyệt có thể viết kịch bản chính kể từ năm 1995:

if (document.getElementById("cb").checked) {...}

Thuộc tính cũng làm cho việc kiểm tra hoặc bỏ chọn hộp kiểm không quan trọng:

document.getElementById("cb").checked = false

Trong jQuery 1.6, điều này rõ ràng trở thành

$("#cb").prop("checked", false)

Ý tưởng sử dụng checkedthuộc tính để kịch bản một hộp kiểm là không có ích và không cần thiết. Tài sản là những gì bạn cần.

  • Không rõ ràng cách chính xác để kiểm tra hoặc bỏ chọn hộp kiểm đang sử dụng checkedthuộc tính
  • Giá trị thuộc tính phản ánh mặc định thay vì trạng thái hiển thị hiện tại (ngoại trừ trong một số phiên bản IE cũ hơn, do đó làm cho mọi thứ vẫn khó khăn hơn). Thuộc tính không cho bạn biết gì về việc hộp kiểm trên trang có được chọn hay không. Xem http://jsfiddle.net/VktA6/49/ .

2
@TJCrowder, cái nào?
Naftali aka Neal

9
@Neal: Nếu bạn muốn biết các thuộc tính DOM có các thuộc tính nào và các thuộc tính có thể gieo các giá trị của chúng như thế nào, hãy giữ các liên kết này trong tay: Đặc tả DOM2 HTML , thông số DOM2 và thông số DOM3 . Các chỉ mục trong mỗi trường hợp là tuyệt vời và liên kết bạn thẳng đến một mô tả kỹ lưỡng về tài sản, nơi giá trị của nó đến, v.v.
TJ Crowder

4
@Neal: Re what what it it: Nguồn và bản chất của thông tin. Nhìn vào valueví dụ của Tim chẳng hạn. Một hàm được gọi là attrtruy xuất thuộc tính value thay vì "giá trị" thuộc tính không có nhiều ý nghĩa (và chúng có thể khác nhau). Đi về phía trước, attrlàm thuộc tính và proplàm thuộc tính sẽ rõ ràng hơn, mặc dù quá trình chuyển đổi sẽ gây đau đớn cho một số người. Đừng hiểu sai về điều này, không có gì giống như lùi lại và đọc thông số kỹ thuật để có ý tưởng về các thuộc tính là gì.
TJ Crowder

54
@Neal: Một phần tử DOM là một đối tượng. Thuộc tính là thuộc tính của đối tượng đó, giống như bất kỳ đối tượng lập trình nào khác. Một số trong các đạo cụ đó nhận các giá trị ban đầu của chúng từ các thuộc tính trong đánh dấu, cũng được lưu trữ trên đối tượng DOM trong một bản đồ các thuộc tính riêng biệt . Trong hầu hết các trường hợp, viết vào một chỗ dựa chỉ thay đổi chỗ dựa, mặc dù đáng buồn là có một số đạo cụ viết bất kỳ thay đổi nào đối với attr cơ bản ( valueví dụ), nhưng chúng ta hãy cố gắng bỏ qua điều đó. 99% thời gian, bạn muốn làm việc với đạo cụ. Nếu bạn cần làm việc với một thuộc tính thực tế, có lẽ bạn sẽ biết điều đó.
TJ Crowder

4
@Tim: "Thay đổi thuộc valuetính của đầu vào không thay đổi valuethuộc tính của nó trong các trình duyệt hiện đại" Tôi không nghĩ là nó đã xảy ra, đó là lý do tại sao tôi bắt đầu sử dụng nó làm ví dụ, nhưng khi tôi bắt đầu viết mã ví dụ, đã mờ đi nếu nó không được cập nhật trên Chrome, Firefox, Opera, IE ... - jsbin.com/ahire4 Hóa ra đó là vì tôi đang sử dụng một input[type="button"]thử nghiệm của mình. Nó không cập nhật thuộc tính trên a input[type="text"]- jsbin.com/ahire4/2 Nói về phức tạp !! Không chỉ là yếu tố, mà là loại của nó ...
TJ Crowder

664

Tôi nghĩ Tim đã nói điều đó khá tốt , nhưng hãy lùi lại:

Một phần tử DOM là một đối tượng, một vật trong bộ nhớ. Giống như hầu hết các đối tượng trong OOP, nó có các thuộc tính . Nó cũng, riêng biệt, có một bản đồ của các thuộc tính được xác định trên thành phần (thường đến từ đánh dấu mà trình duyệt đọc để tạo thành phần). Một số các phần tử thuộc tính được họ ban đầu giá trị từ các thuộc tính với tên giống hoặc tương tự ( valueđược giá trị ban đầu của nó từ thuộc tính "giá trị"; hrefđược giá trị ban đầu của nó từ thuộc tính "href", nhưng đó là không chính xác giá trị như nhau; classNametừ thuộc tính "lớp"). Các thuộc tính khác nhận các giá trị ban đầu của chúng theo các cách khác: Chẳng hạn, thuộc parentNodetính nhận giá trị của nó dựa trên thành phần chính của nó là gì;style tài sản, cho dù nó có thuộc tính "phong cách" hay không.

Hãy xem xét neo này trong một trang tại http://example.com/testing.html:

<a href='foo.html' class='test one' name='fooAnchor' id='fooAnchor'>Hi</a>

Một số nghệ thuật ASCII vô cớ (và bỏ đi rất nhiều thứ):

+ + +
| HTMLAnchorEuity |
+ + +
| href: "http://example.com/foo.html" |
| tên: "fooAnchor" |
| id: "fooAnchor" |
| className: "kiểm tra một" |
| thuộc tính: |
| href: "foo.html" |
| tên: "fooAnchor" |
| id: "fooAnchor" |
| lớp: "kiểm tra một" |
+ + +

Lưu ý rằng các thuộc tính và thuộc tính là khác biệt.

Bây giờ, mặc dù chúng là khác biệt, bởi vì tất cả những thứ này phát triển thay vì được thiết kế từ đầu, một số thuộc tính ghi lại thuộc tính mà chúng bắt nguồn từ nếu bạn đặt chúng. Nhưng không phải tất cả đều như vậy, và như bạn có thể thấy từ hrefphía trên, ánh xạ không phải lúc nào cũng là "truyền giá trị" thẳng, đôi khi có sự diễn giải liên quan.

Khi tôi nói về các thuộc tính là thuộc tính của một đối tượng, tôi không nói một cách trừu tượng. Đây là một số mã không phải jQuery:

var link = document.getElementById('fooAnchor');
alert(link.href);                 // alerts "http://example.com/foo.html"
alert(link.getAttribute("href")); // alerts "foo.html"

(Các giá trị đó theo hầu hết các trình duyệt; có một số biến thể.)

Đối linktượng là một vật thật và bạn có thể thấy có một sự khác biệt thực sự giữa việc truy cập một thuộc tính trên nó và truy cập một thuộc tính .

Như Tim đã nói, phần lớn thời gian, chúng tôi muốn làm việc với các tài sản. Một phần đó là vì giá trị của chúng (thậm chí tên của chúng) có xu hướng phù hợp hơn trên các trình duyệt. Chúng tôi hầu như chỉ muốn làm việc với các thuộc tính khi không có thuộc tính liên quan đến nó (thuộc tính tùy chỉnh) hoặc khi chúng tôi biết rằng đối với thuộc tính cụ thể đó, thuộc tính và thuộc tính không phải là 1: 1 (như với hrefvà "href" ở trên) .

Các thuộc tính tiêu chuẩn được trình bày trong các thông số DOM khác nhau:

Những thông số kỹ thuật này có chỉ số tuyệt vời và tôi khuyên bạn nên giữ liên kết đến chúng tiện dụng; Tôi sử dụng tất cả các thời gian.

Chẳng hạn, các thuộc tính tùy chỉnh sẽ bao gồm bất kỳ data-xyzthuộc tính nào bạn có thể đặt vào các phần tử để cung cấp siêu dữ liệu cho mã của bạn (bây giờ, đó là hợp lệ của HTML5, miễn là bạn tuân theo data-tiền tố). (Các phiên bản gần đây của jQuery cung cấp cho bạn quyền truy cập vào data-xyzcác phần tử thông qua datahàm, nhưng hàm đó không chỉ là một trình truy cập cho các data-xyzthuộc tính [nó thực hiện nhiều hơn và ít hơn thế]; trừ khi bạn thực sự cần các tính năng của nó, tôi sẽ sử dụng attrhàm để tương tác với data-xyzthuộc tính.)

Các attrchức năng đã từng có một số logic phức tạp xung quanh nhận được những gì họ nghĩ bạn muốn, chứ không phải theo nghĩa đen nhận được thuộc tính. Nó kết hợp các khái niệm. Di chuyển đến propattrcó nghĩa là để khử chúng. Một thời gian ngắn trong v1.6.0 jQuery đã đi quá xa trong vấn đề đó, nhưng chức năng đã nhanh chóng được bổ sung trở lại để attrxử lý các tình huống phổ biến mà mọi người sử dụng attrkhi về mặt kỹ thuật họ nên sử dụng prop.


Ồ bản cập nhật 1.6.1 mới đó thực sự vô hiệu hóa câu hỏi này một chút .. (nhưng không nhiều) nhưng về cơ bản liên kết đó trả lời ngay bây giờ
Naftali aka Neal

Nó không vô hiệu hóa nó cho tôi, tôi chỉ sửa một lỗi bằng cách sử dụng jquery1.7 nơi tôi đang đặt .attr ('class', 'bla') và nó không hoạt động ở nơi .prop ('className', 'bla' ) đã làm việc
PandaWood

@PandaWood: .attr('class', 'bla')hoạt động như mong đợi đối với tôi trong 1.7.0 , 1.7.11.7.2 trên Chrome 17, Firefox 11, Opera 11, IE6, IE8, IE9 và Safari 5.
TJ Crowder

Cảm ơn, phải có một cái gì đó cụ thể trong trường hợp của tôi, hãy để tôi kiểm tra điều này và quay lại với một trường hợp thử nghiệm. Nhưng việc thay đổi mã như chúng ta có ngay bây giờ, chỉ đơn giản là "prop / className", thay vì "attr" sửa một lỗi lớn cho chúng ta khi chúng ta chuyển từ jquery1.4 sang 1.7 - trên tất cả các trình duyệt
PandaWood

3
@TJCrowder re: .data- nó sẽ đọc giá trị mặc định của thuộc tính, nếu có, nhưng nếu bạn viết cho nó, nó sẽ thay đổi thuộc tính ẩn của phần tử và không cập nhật thuộc tính.
Alnitak

250

Thay đổi này đã có từ lâu đối với jQuery. Trong nhiều năm, họ đã hài lòng với một hàm có tên attr()hầu hết lấy các thuộc tính DOM, không phải là kết quả mà bạn mong đợi từ tên đó. Việc tách biệt attr()prop()sẽ giúp giảm bớt một số nhầm lẫn giữa các thuộc tính HTML và thuộc tính DOM. $.fn.prop()lấy thuộc tính DOM được chỉ định, trong khi $.fn.attr()lấy thuộc tính HTML được chỉ định.

Để hiểu đầy đủ về cách thức hoạt động của chúng, đây là phần giải thích mở rộng về sự khác biệt giữa các thuộc tính HTML và thuộc tính DOM.:

Thuộc tính HTML

Cú pháp:

<body onload="foo()">

Mục đích: Cho phép đánh dấu có dữ liệu liên quan đến nó cho các sự kiện, kết xuất và các mục đích khác.

Trực quan: Thuộc tính HTML Thuộc tính lớp được hiển thị ở đây trên cơ thể. Nó có thể truy cập thông qua mã sau đây:

var attr;
attr = document.body.getAttribute("class");
//IE 8 Quirks and below
attr = document.body.getAttribute("className");

Các thuộc tính được trả về ở dạng chuỗi và có thể không nhất quán từ trình duyệt này đến trình duyệt khác. Tuy nhiên, chúng có thể rất quan trọng trong một số tình huống. Như đã được minh họa ở trên, Chế độ Quirks IE 8 (và bên dưới) mong muốn tên của một thuộc tính DOM trong get / set / removeAttribution thay vì tên thuộc tính. Đây là một trong nhiều lý do tại sao điều quan trọng là phải biết sự khác biệt.

Thuộc tính DOM

Cú pháp:

document.body.onload = foo;

Mục đích: Cung cấp quyền truy cập vào các thuộc tính thuộc về các nút phần tử. Các thuộc tính này tương tự như các thuộc tính, nhưng chỉ có thể truy cập thông qua JavaScript. Đây là một sự khác biệt quan trọng giúp làm rõ vai trò của các thuộc tính DOM. Xin lưu ý rằng các thuộc tính hoàn toàn khác với các thuộc tính , vì việc gán xử lý sự kiện này là vô ích và sẽ không nhận được sự kiện (cơ thể không có sự kiện onload, chỉ có thuộc tính onload).

Hình dung: Thuộc tính DOM

Tại đây, bạn sẽ nhận thấy một danh sách các thuộc tính trong tab "DOM" trong Fireorms. Đây là các thuộc tính DOM. Bạn sẽ ngay lập tức nhận thấy khá nhiều trong số họ, vì bạn sẽ sử dụng chúng trước đây mà không biết. Giá trị của chúng là những gì bạn sẽ nhận được thông qua JavaScript.

Tài liệu

Thí dụ

HTML: <textarea id="test" value="foo"></textarea>

JavaScript: alert($('#test').attr('value'));

Trong các phiên bản trước của jQuery, điều này trả về một chuỗi rỗng. Trong 1.6, nó trả về giá trị thích hợp , foo.

Không cần liếc qua mã mới cho một trong hai chức năng, tôi có thể tự tin nói rằng sự nhầm lẫn có liên quan nhiều đến sự khác biệt giữa các thuộc tính HTML và thuộc tính DOM, hơn là với chính mã. Hy vọng, điều này đã xóa một số điều cho bạn.

-Matt


7
$.prop()được các thuộc tính DOM, $.attr()có các thuộc tính HTML. Tôi đang cố gắng thu hẹp khoảng cách về mặt tâm lý để bạn có thể hiểu được sự khác biệt giữa hai người.

10
Chàng trai, tôi cũng bối rối. Vì vậy, $('#test').prop('value')không trả lại bất cứ điều gì? Cũng không .attr('checked')cho một hộp kiểm tra? Nhưng nó đã từng? Bây giờ bạn phải thay đổi nó thành prop('checked')? Tôi không hiểu sự cần thiết của sự khác biệt này - tại sao việc phân biệt giữa các thuộc tính HTML và thuộc tính DOM lại quan trọng? Trường hợp sử dụng phổ biến đã tạo ra sự thay đổi này "một thời gian dài sắp tới" là gì? Có gì sai khi trừu tượng hóa sự khác biệt giữa hai người, vì có vẻ như các trường hợp sử dụng của họ chủ yếu trùng nhau?
BlueRaja - Daniel Pflughoeft

5
@BlueRaja: bởi vì có một sự khác biệt tiềm ẩn nghiêm trọng giữa hai khái niệm mà nếu bạn chải nó dưới tấm thảm như jQuery đã từng sử dụng, sẽ dẫn đến những thất bại không mong muốn. valuelà một trong những trường hợp rõ ràng nhất, vì thuộc valuetính sẽ cung cấp cho bạn giá trị hiện tại của một trường, nhưng valuethuộc tính sẽ cung cấp cho bạn giá trị ban đầu được khai báo trong value="..."thuộc tính, thực sự là thuộc defaultValuetính. (Mặc dù trường hợp cụ thể này lại bị nhầm lẫn bởi các lỗi trong IE <9.)
bobince

4
@BlueRaja: Câu trả lời thậm chí còn phức tạp hơn. :-) Cài đặt attr('value', ...)trong jQuery <1.6 đặt thuộc tính, vì vậy giá trị hiện tại thay đổi và giá trị mặc định thì không. Trong 1.6, nó đặt thuộc tính, vì vậy về mặt lý thuyết, giá trị mặc định thay đổi và giá trị hiện tại thì không. Tuy nhiên, có (không) trình duyệt không nhất quán về việc cài đặt chính xác valuethuộc tính này. Trong IE, nó cũng đặt giá trị hiện tại; trong một số trình duyệt, nó chỉ đặt giá trị hiện tại nếu giá trị hiện tại chưa được đặt trước đó. [khóc]
bobince

1
Giống như @Quentin đã nói, "Các thuộc tính được xác định bởi HTML. Các thuộc tính được xác định bởi DOM." Phiên bản đơn giản nhất mà tôi đã đọc.
Alan Dong

241

Một thuộc tính nằm trong DOM; một thuộc tính có trong HTML được phân tích cú pháp vào DOM.

Thêm chi tiết

Nếu bạn thay đổi một thuộc tính, thay đổi sẽ được phản ánh trong DOM (đôi khi có một tên khác).

Ví dụ: Thay đổi classthuộc tính của thẻ sẽ thay đổi thuộc classNametính của thẻ đó trong DOM. Nếu bạn không có thuộc tính trên thẻ, bạn vẫn có thuộc tính DOM tương ứng với giá trị trống hoặc giá trị mặc định.

Ví dụ: Mặc dù thẻ của bạn không có classthuộc tính, thuộc tính DOM classNametồn tại với giá trị chuỗi trống.

biên tập

Nếu bạn thay đổi cái khác, cái khác sẽ được thay đổi bởi bộ điều khiển và ngược lại. Bộ điều khiển này không có trong jQuery, nhưng trong mã gốc của trình duyệt.


Vì vậy, điều này có nghĩa là tốt hơn để cập nhật thuộc tính bởi vì sau đó bạn đang đảm bảo rằng cả thuộc tính và thuộc tính đều được cập nhật và được căn chỉnh?
Lu-ca

1
@Luke DOM là đại diện kỹ thuật bên trong, mô hình. Các thuộc tính HTML là một đại diện bên ngoài, một khung nhìn. Nếu bạn thay đổi cái khác, cái khác sẽ được thay đổi bởi bộ điều khiển và ngược lại.
yunzen

@HerrSerker Vậy cả hai đều được giữ đồng bộ qua bộ điều khiển? Tôi giả sử đây chỉ là trong các phương thức attr và prop của jQuery? Đây là một sửa đổi của fiddle của bạn, nơi tôi khám phá điều này nhiều hơn - jsfiddle.net/v8wRy - và cho đến nay chúng dường như tương đương nhau.
Lu-ca

3
"Nếu bạn thay đổi cái này, cái kia sẽ được thay đổi bởi bộ điều khiển và ngược lại. Bộ điều khiển này không có trong jQuery, mà là mã gốc của trình duyệt." Điều này không đúng với hầu hết các thuộc tính / thuộc tính. Đối với đa số, đó chỉ là bản dịch một chiều trong đó một thuộc tính xác định giá trị ban đầu của thuộc tính tương ứng. Hai câu trả lời hàng đầu giải thích điều này một cách chi tiết.
ᴠɪɴᴄᴇɴᴛ

@Vincent. Tôi không thấy, nơi hai câu trả lời hàng đầu nói điều gì đó trái ngược với câu trả lời của tôi. Tất nhiên hầu hết các thuộc tính là các giá trị ban đầu của các thuộc tính DOM tương ứng. Nhưng họ phụ thuộc lẫn nhau. Hãy thử một cái gì đó giống như jQuery('p').prop('className', 'foo');trong bảng điều khiển Chrome và bạn sẽ thấy, làm thế nào mỗi đoạn có classthuộc tính Jun của 'foo'. Tất nhiên không phải trong mã nguồn, xuất phát từ máy chủ. Đó là một hằng số.
yunzen

140

Đó chỉ là sự phân biệt giữa các thuộc tính HTML và các đối tượng DOM gây nhầm lẫn. Đối với những người thoải mái hành động trên các thuộc tính nguyên tố DOM this.src this.value this.checked, v.v., .proplà một sự chào đón rất nồng hậu cho gia đình. Đối với những người khác, nó chỉ là một lớp nhầm lẫn thêm. Hãy làm rõ điều đó lên.

Cách dễ nhất để thấy sự khác biệt giữa .attr.proplà ví dụ sau:

<input blah="hello">
  1. $('input').attr('blah'): trả về 'hello'như mong đợi. Không có bất ngờ ở đây.
  2. $('input').prop('blah'): trả về undefined- bởi vì nó đang cố gắng thực hiện [HTMLInputElement].blah- và không có thuộc tính nào như vậy trên đối tượng DOM đó tồn tại. Nó chỉ tồn tại trong phạm vi như một thuộc tính của thành phần đó, tức là[HTMLInputElement].getAttribute('blah')

Bây giờ chúng tôi thay đổi một số thứ như vậy:

$('input').attr('blah', 'apple');
$('input').prop('blah', 'pear');
  1. $('input').attr('blah'): trả về 'apple'hả? Tại sao không "lê" vì điều này đã được đặt cuối cùng trên phần tử đó. Bởi vì thuộc tính đã được thay đổi trên thuộc tính đầu vào, chứ không phải chính phần tử đầu vào DOM - về cơ bản chúng gần như hoạt động độc lập với nhau.
  2. $('input').prop('blah'): trả về 'pear'

Điều bạn thực sự cần phải cẩn thận chỉ là không trộn lẫn việc sử dụng chúng cho cùng một thuộc tính trong toàn bộ ứng dụng của bạn vì lý do trên.

Xem một câu đố thể hiện sự khác biệt: http://jsfiddle.net/garreh/uLQXc/


.attrvs .prop:

Vòng 1: phong cách

<input style="font:arial;"/>
  • .attr('style') - trả về kiểu nội tuyến cho phần tử phù hợp tức là "font:arial;"
  • .prop('style') - trả về một đối tượng khai báo kiểu CSSStyleDeclaration

Vòng 2: giá trị

<input value="hello" type="text"/>   

$('input').prop('value', 'i changed the value');
  • .attr('value')- trả về 'hello'*
  • .prop('value') - trả lại 'i changed the value'

* Lưu ý: jQuery vì lý do này có một .val()phương thức, bên trong tương đương với.prop('value')


@Neal bởi vì nó cung cấp tham chiếu đến cấu trúc của các hàm jquery tốt hơn. "$ ('input'). prop ('blah'): trả về không xác định - bởi vì nó đang cố gắng thực hiện [HTMLInputEuity] .blah - và không tồn tại thuộc tính như vậy trên đối tượng DOM đó. Nó chỉ tồn tại trong phạm vi như một thuộc tính của phần tử đó, tức là [HTMLInputEuity] .getAttribution ('blah') "
Uğur Gümüşhan

2
Có vẻ khác với doc, api.jquery.com/prop : "Nên sử dụng phương thức .prop () để đặt bị vô hiệu hóa và được kiểm tra thay vì phương thức .attr (). Nên sử dụng phương thức .val () để lấy và giá trị cài đặt."
thiên nga

53

TL; DR

Sử dụng prop()hơn attr()trong phần lớn các trường hợp.

Một thuộc tính là trạng thái hiện tại của phần tử đầu vào. Một thuộc tính là giá trị mặc định.

Một tài sản có thể chứa những thứ thuộc các loại khác nhau. Một thuộc tính chỉ có thể chứa chuỗi


1
nếu có thể đi kèm với một vài mẫu dễ dàng về những gì bạn nói và cũng hiển thị khi sử dụng prop() and when to go for attr(). chờ câu trả lời :)
Mou

36

Kiểm tra bẩn

Khái niệm này cung cấp một ví dụ trong đó sự khác biệt có thể quan sát được: http://www.w3.org/TR/html5/forms.html#concept-input-checked-denty

Dùng thử:

  • ấn nút. Cả hai hộp kiểm tra đã được kiểm tra.
  • bỏ chọn cả hai hộp kiểm.
  • nhấp vào nút một lần nữa. Chỉ có prophộp kiểm tra được kiểm tra. BANG!

$('button').on('click', function() {
  $('#attr').attr('checked', 'checked')
  $('#prop').prop('checked', true)
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<label>attr <input id="attr" type="checkbox"></label>
<label>prop <input id="prop" type="checkbox"></label>
<button type="button">Set checked attr and prop.</button>

Đối với một số thuộc tính như disabledtrên button, việc thêm hoặc xóa thuộc tính nội dung disabled="disabled"luôn bật thuộc tính (được gọi là thuộc tính IDL trong HTML5) vì http://www.w3.org/TR/html5/forms.html#attr-fe-disables nói:

Thuộc tính IDL bị vô hiệu hóa phải phản ánh thuộc tính nội dung bị vô hiệu hóa.

vì vậy bạn có thể thoát khỏi nó, mặc dù nó xấu vì nó sửa đổi HTML mà không cần.

Đối với các thuộc tính khác như checked="checked"trên input type="checkbox", mọi thứ sẽ bị hỏng, bởi vì một khi bạn nhấp vào nó, nó sẽ trở nên bẩn, và sau đó thêm hoặc xóa checked="checked"thuộc tính nội dung sẽ không chuyển đổi kiểm tra nữa .

Đây là lý do tại sao bạn nên sử dụng chủ yếu .prop, vì nó ảnh hưởng trực tiếp đến thuộc tính hiệu quả, thay vì dựa vào các tác dụng phụ phức tạp của việc sửa đổi HTML.


Để hoàn thiện, hãy thử các biến thể sau: 1) Trước khi nhấp vào nút kiểm tra và sau đó bỏ chọn hộp kiểm đầu tiên 2) (Đối với cái này, bạn sẽ cần thay đổi đoạn trích) Cung cấp checkedthuộc tính đầu vào đầu tiên :checked="checked"
ᴠɪɴᴄᴇɴᴛ

33

Tất cả là trong tài liệu :

Sự khác biệt giữa các thuộc tính và thuộc tính có thể quan trọng trong các tình huống cụ thể. Trước jQuery 1.6, phương thức .attr () đôi khi đã tính đến các giá trị thuộc tính khi truy xuất một số thuộc tính, điều này có thể gây ra hành vi không nhất quán. Kể từ jQuery 1.6, phương thức .prop () cung cấp một cách để truy xuất rõ ràng các giá trị thuộc tính, trong khi .attr () lấy các thuộc tính.

Vì vậy, sử dụng prop!


2
Vậy có nghĩa là khi tôi chuyển sang 1.6, rất nhiều thứ sẽ vỡ ??
Naftali aka Neal

Không, đó chỉ là một hành vi không nhất quán, nếu nó hoạt động trước đó, nó sẽ luôn hoạt động với jQuery 1.6, chỉ là prop đó an toàn hơn;)
Arnaud F.

6
Tôi dường như nhớ lại. $.attr()lấy các thuộc tính hầu hết thời gian tôi làm việc với nó, không phải "đôi khi". Sự nhầm lẫn gây ra bởi nó vẫn còn vang dội cho đến ngày hôm nay. Đáng buồn thay, tôi gặp rất nhiều khó khăn khi tìm cách đọc chính xác các thuộc tính HTML so với các thuộc tính DOM, vì vậy tôi có thể viết một câu trả lời ở đây một chút.

3
@ Arnaud-f Không đúng. Tất cả các mã trước 1.6 sử dụng attr ('đã kiểm tra') để kiểm tra các hộp kiểm sẽ bị hỏng.
CaptSaltyJack

3
@Matt McDonald: Ý bạn là gì "... gặp khó khăn khi tìm đọc chính xác các thuộc tính HTML so với các thuộc tính DOM ..."? Các thuộc tính (được phản ánh và mặt khác) được mô tả trong đặc tả DOM2 HTML ; bạn cũng có thể cần tham khảo thông số kỹ thuật DOM2DOM3 .
TJ Crowder

28

các thuộc tính có trong tài liệu / tệp văn bản HTML của bạn (== hãy tưởng tượng đây là kết quả của việc đánh dấu html của bạn được phân tích cú pháp), trong khi
các thuộc tính nằm trong cây DOM DOM (về cơ bản là một thuộc tính thực tế của một số đối tượng theo nghĩa của JS).

Điều quan trọng, nhiều trong số chúng được đồng bộ hóa (nếu bạn cập nhật thuộc tính class, classthuộc tính trong html cũng sẽ được cập nhật; và nếu không). Nhưng một số thuộc tính có thể được đồng bộ hóa với tính chất bất ngờ - ví dụ, thuộc tính checked tương ứng với tài sản defaultChecked , do đó

  • kiểm tra thủ công một hộp kiểm sẽ thay đổi .prop('checked')giá trị, nhưng sẽ không thay đổi .attr('checked').prop('defaultChecked')giá trị
  • cài đặt $('#input').prop('defaultChecked', true)cũng sẽ thay đổi .attr('checked'), nhưng điều này sẽ không hiển thị trên một phần tử.

Nguyên tắc chung là : .prop()phương thức nên được sử dụng cho các thuộc tính / thuộc tính boolean và cho các thuộc tính không tồn tại trong html (như window.location). Tất cả các thuộc tính khác (những thuộc tính bạn có thể thấy trong html) có thể và nên tiếp tục được thao tác với .attr() phương thức. ( http://blog.jquery.com/2011/05/10/jquery-1-6-1-rc-1-release/ )

Và đây là bảng hiển thị nơi .prop()được ưu tiên (mặc dù .attr()vẫn có thể được sử dụng).

bảng với cách sử dụng ưu tiên


Tại sao đôi khi bạn muốn sử dụng .prop () thay vì .attr () trong đó sau này được chính thức khuyến khích?

  1. .prop()có thể trả về bất kỳ loại nào - chuỗi, số nguyên, boolean; trong khi .attr()luôn trả về một chuỗi
  2. .prop()được cho là nhanh hơn khoảng 2,5 lần .attr().

một cái gì đó đã được thay đổi, như thế này: $('#myImageId').prop('src', 'http://example.com/img.png'), var class = $('.myDivClass').prop('class'), hoặc $('#myTextBox').prop('type', 'button'). Và cứ thế ...

@ Mr.Wolf, xin lỗi, tôi vẫn không hiểu ý bạn. Điều gì đã "thay đổi"? cú pháp luôn luôn như vậy.
lakeare

Tôi nghĩ rằng bảng trong câu trả lời của bạn là không cần thiết. Bởi vì .prop()hoạt động tốt với tất cả các thuộc tính. Bạn không muốn đánh dấu tất cả các thuộc tính trong .prop()cột, phải không?

@ Mr.Wolf, tôi nghĩ điều đó là cần thiết, bởi vì, như đã nêu, nó 'hiển thị nơi .prop()được ưu tiên (mặc dù .attr()vẫn có thể được sử dụng)'
lakeare

Tôi thường sử dụng .attr()để xác định một sự kiện những gì .prop()không thể. Như thế này : $('.myDiv').attr('onclick', 'alert("Hello world!")'). Nếu bạn đổi .attr()thành .prop(), nó sẽ không hoạt động. Hoàn toàn, tôi nghĩ không có lý do để sử dụng .attr()để thiết lập hoặc nhận giá trị id/class/href/checked/src...... Lưu ý rằng tôi không nói bạn sai.

20

.attr():

  • Lấy giá trị của một thuộc tính cho phần tử đầu tiên trong tập hợp các phần tử phù hợp.
  • Cung cấp cho bạn giá trị của phần tử như được xác định trong html khi tải trang

.prop():

  • Lấy giá trị của một thuộc tính cho phần tử đầu tiên trong tập hợp các phần tử khớp.
  • Cung cấp các giá trị cập nhật của các yếu tố được sửa đổi thông qua javascript / jquery

13

Thông thường bạn sẽ muốn sử dụng tài sản. Chỉ sử dụng các thuộc tính cho:

  1. Nhận một thuộc tính HTML tùy chỉnh (vì nó không được đồng bộ hóa với thuộc tính DOM).
  2. Lấy thuộc tính HTML không đồng bộ hóa với thuộc tính DOM, ví dụ: lấy "giá trị gốc" của thuộc tính HTML tiêu chuẩn, như <input value="abc">.

7

attributes -> HTML

properties -> DOM


8
Tôi biết những gì bạn muốn nói, nhưng HTML là một ngôn ngữ đánh dấu và DOM là một đại diện được tạo ra từ HTML. Một DOMEuity có cả thuộc tínhthuộc tính .
t.niese

@ t.niese, attirbutescũng là một trong những tài sản củaDOM
NkS

Câu trả lời ngắn gọn là đơn giản.
Nabi KAZ

6

Trước jQuery 1.6, attr()phương thức đôi khi đã tính đến các giá trị thuộc tính khi truy xuất các thuộc tính, điều này gây ra hành vi khá không nhất quán.

Việc giới thiệu prop()phương thức cung cấp một cách để truy xuất các giá trị .attr()thuộc tính một cách rõ ràng, trong khi lấy các thuộc tính.

Tài liệu:

jQuery.attr() Lấy giá trị của một thuộc tính cho phần tử đầu tiên trong tập hợp các phần tử phù hợp.

jQuery.prop() Lấy giá trị của một thuộc tính cho phần tử đầu tiên trong tập hợp các phần tử khớp.


3

Nhắc nhở nhẹ nhàng về việc sử dụng prop(), ví dụ:

if ($("#checkbox1").prop('checked')) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Hàm trên được sử dụng để kiểm tra xem hộp kiểm1 có được chọn hay không, nếu được chọn: return 1; if not: return 0. Hàm prop () được sử dụng ở đây dưới dạng hàm GET.

if ($("#checkbox1").prop('checked', true)) {
    isDelete = 1;
} else {
    isDelete = 0;
}

Hàm trên được sử dụng để đặt hộp kiểm1 được kiểm tra và LUÔN LUÔN trả về 1. Bây giờ hàm prop () được sử dụng làm hàm SET.

Đừng gây rối.

P / S: Khi tôi kiểm tra thuộc tính Image src . Nếu src trống, prop trả về URL hiện tại của trang (sai) và attr trả về chuỗi trống (phải).


Bạn đã sai trong ví dụ này : <img src="smiley.gif" alt="Smiley face" width="42" height="42" onclick="alert($(this).prop('src'))">. Nó sẽ làm việc và trả lại vị trí hình ảnh.

2

Một điều .attr()có thể làm là .prop()không thể: ảnh hưởng đến các bộ chọn CSS

Đây là một vấn đề tôi không thấy trong các câu trả lời khác.

Bộ chọn CSS [name=value]

  • sẽ trả lời .attr('name', 'value')
  • nhưng không phải lúc nào cũng để .prop('name', 'value')

.prop() chỉ ảnh hưởng đến một vài bộ chọn thuộc tính

.attr() ảnh hưởng đến tất cả các bộ chọn thuộc tính


0

1) Một tài sản nằm trong DOM; một thuộc tính có trong HTML được phân tích cú pháp vào DOM.

2) $ (elem) .attr ("đã kiểm tra") (1.6.1+) "đã kiểm tra" (Chuỗi) Sẽ thay đổi với trạng thái hộp kiểm

3) $ (elem) .attr ("đã kiểm tra") (trước 1.6) đúng (Boolean) Thay đổi với trạng thái hộp kiểm

  • Chủ yếu chúng tôi muốn sử dụng cho đối tượng DOM thay vì thuộc tính tùy chỉnh như thế nào data-img, data-xyz.

  • Ngoài ra, một số khác biệt khi truy cập checkboxgiá trị và href với attr()prop()điều thay đổi với đầu ra DOM với prop()liên kết đầy đủ từ originBooleangiá trị cho hộp kiểm (pre-1.6)

  • Chúng tôi chỉ có thể truy cập các phần tử DOM với propnhau.undefined


0

Có một vài cân nhắc nữa trong prop () vs attr ():

  • chọn Index, tagName, nodeName, nodeType, ownDocument, defaultChecked và defaultSelected..etc nên được truy xuất và thiết lập với phương thức .prop (). Chúng không có thuộc tính tương ứng và chỉ là thuộc tính.

  • Đối với hộp kiểm loại đầu vào

       .attr('checked') //returns  checked
       .prop('checked') //returns  true
       .is(':checked') //returns true
  • Phương thức prop trả về giá trị Boolean cho đã chọn, đã chọn, bị vô hiệu hóa, readOnly..etc trong khi attr trả về chuỗi được xác định. Vì vậy, bạn có thể trực tiếp sử dụng .prop ('đã kiểm tra') trong điều kiện if.

  • .attr () gọi .prop () bên trong nên phương thức .attr () sẽ chậm hơn một chút so với truy cập trực tiếp qua .prop ().


-2

Câu trả lời của Gary Hole rất phù hợp để giải quyết vấn đề nếu mã được viết theo cách như vậy

obj.prop("style","border:1px red solid;")

CSSStyleDeclarationđối tượng trả về hàm prop , mã trên sẽ không hoạt động đúng trong một số trình duyệt (được thử nghiệm IE8 with Chrome Frame Plugintrong trường hợp của tôi).

Do đó, thay đổi nó thành mã sau đây

obj.prop("style").cssText = "border:1px red solid;"

Đã giải quyết vấn đề.

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.