Câu trả lời:
Bạn phải luôn luôn sử dụng .attribute
biểu mẫu trực tiếp (nhưng xem liên kết quirksmode bên dưới) nếu bạn muốn truy cập theo chương trình trong JavaScript. Nó sẽ xử lý các loại thuộc tính khác nhau (nghĩ "onload") một cách chính xác.
Sử dụng getAttribute
/ setAttribute
khi bạn muốn xử lý DOM như hiện tại (ví dụ: chỉ văn bản bằng chữ). Các trình duyệt khác nhau gây nhầm lẫn cho hai. Xem chế độ Quirks: tương thích thuộc tính (trong) .
Từ Javascript: Hướng dẫn dứt khoát , nó làm rõ mọi thứ. Nó lưu ý rằng các đối tượng HTMLE bổ sung của tài liệu HTML xác định các thuộc tính JS tương ứng với tất cả các thuộc tính HTML tiêu chuẩn.
Vì vậy, bạn chỉ cần sử dụng setAttribute
cho các thuộc tính không chuẩn.
Thí dụ:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborder
KHÔNG được xác định, vì vậy bạn phải getAttribution để lấy lại giá trị.
frameBorder
trực tiếp, nhưng lưu ý viết hoa. Ai đó nghĩ rằng đó là một ý tưởng hay để camelCase tương đương JavaScript của các thuộc tính HTML. Tôi đã không quản lý để tìm thấy bất kỳ đặc điểm kỹ thuật nào cho việc này, nhưng mạng dường như đồng ý rằng đó là vấn đề của 12 trường hợp cụ thể (ít nhất là đối với HTML 4). Xem ví dụ bài sau: drupal.org/node/1420706#comment-6423420
usemap
thuộc tính không thể được thiết lập bằng cách sử dụng ký hiệu dấu chấm khi tạo bản đồ tự động cho một hình ảnh. Nó đòi hỏi img.setAttribute('usemap', "#MapName");
Câu trả lời của bạn có ngụ ý rằng usemap
"không chuẩn" không?
Không có câu trả lời nào trước đây là đầy đủ và hầu hết đều chứa thông tin sai lệch.
Có ba cách truy cập các thuộc tính của Phần tử DOM trong JavaScript. Cả ba đều hoạt động đáng tin cậy trong các trình duyệt hiện đại miễn là bạn hiểu cách sử dụng chúng.
element.attributes
Các yếu tố có một tài sản thuộc tính rằng lợi nhuận một live NamedNodeMap của attr đối tượng. Các chỉ mục của bộ sưu tập này có thể khác nhau giữa các trình duyệt. Vì vậy, thứ tự không được đảm bảo. NamedNodeMap
có các phương thức để thêm và xóa các thuộc tính ( getNamedItem
và setNamedItem
, tương ứng).
Lưu ý rằng mặc dù XML phân biệt chữ hoa chữ thường rõ ràng, nhưng thông số DOM gọi các tên chuỗi được chuẩn hóa , do đó các tên được truyền vào getNamedItem
không phân biệt chữ hoa chữ thường.
var div = document.getElementsByTagName('div')[0];
//you can look up specific attributes
var classAttr = div.attributes.getNamedItem('CLASS');
document.write('attributes.getNamedItem() Name: ' + classAttr.name + ' Value: ' + classAttr.value + '<br>');
//you can enumerate all defined attributes
for(var i = 0; i < div.attributes.length; i++) {
var attr = div.attributes[i];
document.write('attributes[] Name: ' + attr.name + ' Value: ' + attr.value + '<br>');
}
//create custom attribute
var customAttr = document.createAttribute('customTest');
customAttr.value = '567';
div.attributes.setNamedItem(customAttr);
//retreive custom attribute
customAttr = div.attributes.getNamedItem('customTest');
document.write('attributes.getNamedItem() Name: ' + customAttr.name + ' Value: ' + customAttr.value + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.getAttribute
&element.setAttribute
Các phương thức này tồn tại trực tiếp trên Element
mà không cần truy cập attributes
và các phương thức của nó nhưng thực hiện các chức năng tương tự.
Một lần nữa, lưu ý rằng tên chuỗi không phân biệt chữ hoa chữ thường.
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.getAttribute('class') + '<br>');
document.write('Name: ID Value: ' + div.getAttribute('ID') + '<br>');
document.write('Name: DATA-TEST Value: ' + div.getAttribute('DATA-TEST') + '<br>');
document.write('Name: nonStandard Value: ' + div.getAttribute('nonStandard') + '<br>');
//create custom attribute
div.setAttribute('customTest', '567');
//retreive custom attribute
document.write('Name: customTest Value: ' + div.getAttribute('customTest') + '<br>');
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
element.id
Nhiều thuộc tính có thể được truy cập bằng các thuộc tính thuận tiện trên đối tượng DOM. Những thuộc tính nào tồn tại phụ thuộc vào loại nút của DOM, chứ không phải thuộc tính nào được xác định trong HTML. Các thuộc tính được định nghĩa ở đâu đó trong chuỗi nguyên mẫu của đối tượng DOM được đề cập. Các thuộc tính cụ thể được xác định sẽ phụ thuộc vào loại Phần tử bạn đang truy cập. Ví dụ, className
và id
được định nghĩa trên Element
và tồn tại trên tất cả các nút DOM là các phần tử (nghĩa là không phải nút văn bản hoặc nút nhận xét). Nhưng value
hẹp hơn. Nó được định nghĩa trên HTMLInputElement
và có thể không tồn tại trên các yếu tố khác.
Lưu ý rằng các thuộc tính JavaScript là trường hợp nhạy cảm. Mặc dù hầu hết các thuộc tính sẽ sử dụng chữ thường, một số là camelCase. Vì vậy, luôn luôn kiểm tra thông số kỹ thuật để chắc chắn.
"Biểu đồ" này nắm bắt một phần của chuỗi nguyên mẫu cho các đối tượng DOM này. Nó thậm chí không gần hoàn thành, nhưng nó nắm bắt cấu trúc tổng thể.
____________Node___________
| | |
Element Text Comment
| |
HTMLElement SVGElement
| |
HTMLInputElement HTMLSpanElement
var div = document.getElementsByTagName('div')[0];
//get specific attributes
document.write('Name: class Value: ' + div.className + '<br>');
document.write('Name: id Value: ' + div.id + '<br>');
document.write('Name: ID Value: ' + div.ID + '<br>'); //undefined
document.write('Name: data-test Value: ' + div.dataset.test + '<br>'); //.dataset is a special case
document.write('Name: nonStandard Value: ' + div.nonStandard + '<br>'); //undefined
<div class="class1" id="main" data-test="stuff" nonStandard="1234"></div>
Hãy cẩn thận: Đây là một lời giải thích về cách xác định HTML và các trình duyệt hiện đại xử lý các thuộc tính. Tôi đã không cố gắng để đối phó với những hạn chế của các trình duyệt bị hỏng, cổ xưa. Nếu bạn cần hỗ trợ các trình duyệt cũ, ngoài thông tin này, bạn sẽ cần biết những gì bị hỏng trong các trình duyệt đó.
Một trường hợp tôi tìm thấy khi setAttribute
cần thiết là khi thay đổi thuộc tính ARIA, vì không có thuộc tính tương ứng. Ví dụ
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
Không có x.arialabel
hoặc bất cứ điều gì tương tự, vì vậy bạn phải sử dụng setAttribution.
Chỉnh sửa: x ["aria-nhãn"] không hoạt động . Bạn thực sự cần setAttribution.
x.getAttribute('aria-label')
null
x["aria-label"] = "Test"
"Test"
x.getAttribute('aria-label')
null
x.setAttribute('aria-label', 'Test2')
undefined
x["aria-label"]
"Test"
x.getAttribute('aria-label')
"Test2"
Những câu trả lời này không thực sự giải quyết được sự nhầm lẫn lớn giữa các thuộc tính và thuộc tính . Ngoài ra, tùy thuộc vào nguyên mẫu Javascript, đôi khi bạn có thể sử dụng thuộc tính của một thành phần để truy cập một thuộc tính và đôi khi bạn không thể.
Đầu tiên, bạn phải nhớ rằng an HTMLElement
là một đối tượng Javascript. Giống như tất cả các đối tượng, chúng có thuộc tính. Chắc chắn, bạn có thể tạo một thuộc tính được gọi là gần như mọi thứ bạn muốn bên trong HTMLElement
, nhưng nó không phải làm bất cứ điều gì với DOM (những gì trên trang). Ký hiệu dấu chấm ( .
) là dành cho các thuộc tính . Bây giờ, có một số thuộc tính đặc biệt được ánh xạ tới các thuộc tính, và tại thời điểm hoặc viết chỉ có 4 thuộc tính được đảm bảo (nhiều hơn về sau).
Tất cả HTMLElement
bao gồm một tài sản được gọi là attributes
. HTMLElement.attributes
là một đối tượng trực tiếp NamedNodeMap
liên quan đến các yếu tố trong DOM. "Live" có nghĩa là khi nút thay đổi trong DOM, chúng sẽ thay đổi ở phía JavaScript và ngược lại. Thuộc tính DOM, trong trường hợp này, là các nút trong câu hỏi. A Node
có một .nodeValue
tài sản mà bạn có thể thay đổi. NamedNodeMap
các đối tượng có một hàm được gọi là setNamedItem
nơi bạn có thể thay đổi toàn bộ nút. Bạn cũng có thể truy cập trực tiếp vào nút bằng phím. Ví dụ, bạn có thể nói .attributes["dir"]
cái nào giống như .attributes.getNamedItem('dir');
(Ghi chú bên, NamedNodeMap
không phân biệt chữ hoa chữ thường, vì vậy bạn cũng có thể vượt qua 'DIR'
);
Có một chức năng tương tự trực tiếp trong HTMLElement
đó bạn chỉ có thể gọi setAttribute
nó sẽ tự động tạo một nút nếu nó không tồn tại và đặt nodeValue
. Ngoài ra còn có một số thuộc tính bạn có thể truy cập trực tiếp dưới dạng các thuộc tính HTMLElement
thông qua các thuộc tính đặc biệt , chẳng hạn như dir
. Đây là một bản đồ sơ bộ của nó trông như thế nào:
HTMLElement {
attributes: {
setNamedItem: function(attr, newAttr) {
this[attr] = newAttr;
},
getNamedItem: function(attr) {
return this[attr];
},
myAttribute1: {
nodeName: 'myAttribute1',
nodeValue: 'myNodeValue1'
},
myAttribute2: {
nodeName: 'myAttribute2',
nodeValue: 'myNodeValue2'
},
}
setAttribute: function(attr, value) {
let item = this.attributes.getNamedItem(attr);
if (!item) {
item = document.createAttribute(attr);
this.attributes.setNamedItem(attr, item);
}
item.nodeValue = value;
},
getAttribute: function(attr) {
return this.attributes[attr] && this.attributes[attr].nodeValue;
},
dir: // Special map to attributes.dir.nodeValue || ''
id: // Special map to attributes.id.nodeValue || ''
className: // Special map to attributes.class.nodeValue || ''
lang: // Special map to attributes.lang.nodeValue || ''
}
Vì vậy, bạn có thể thay đổi các dir
thuộc tính 6 cách:
// 1. Replace the node with setNamedItem
const newAttribute = document.createAttribute('dir');
newAttribute.nodeValue = 'rtl';
element.attributes.setNamedItem(newAttribute);
// 2. Replace the node by property name;
const newAttribute2 = document.createAttribute('dir');
newAttribute2.nodeValue = 'rtl';
element.attributes['dir'] = newAttribute2;
// OR
element.attributes.dir = newAttribute2;
// 3. Access node with getNamedItem and update nodeValue
// Attribute must already exist!!!
element.attributes.getNamedItem('dir').nodeValue = 'rtl';
// 4. Access node by property update nodeValue
// Attribute must already exist!!!
element.attributes['dir'].nodeValue = 'rtl';
// OR
element.attributes.dir.nodeValue = 'rtl';
// 5. use setAttribute()
element.setAttribute('dir', 'rtl');
// 6. use the UNIQUELY SPECIAL dir property
element["dir"] = 'rtl';
element.dir = 'rtl';
Bạn có thể cập nhật tất cả các thuộc tính với phương pháp # 1-5, nhưng chỉ dir
, id
, lang
, và className
với phương pháp # 6.
HTMLElement
có 4 tính chất đặc biệt Một số phần tử là các lớp mở rộng HTMLElement
có các thuộc tính được ánh xạ nhiều hơn. Ví dụ, HTMLAnchorElement
có HTMLAnchorElement.href
, HTMLAnchorElement.rel
và HTMLAnchorElement.target
. Nhưng, hãy cẩn thận , nếu bạn đặt các thuộc tính đó trên các thành phần không có các thuộc tính đặc biệt đó (như trên a HTMLTableElement
) thì các thuộc tính không thay đổi và chúng chỉ là các thuộc tính tùy chỉnh thông thường. Để hiểu rõ hơn, đây là một ví dụ về sự kế thừa của nó:
HTMLAnchorElement extends HTMLElement {
// inherits all of HTMLElement
href: // Special map to attributes.href.nodeValue || ''
target: // Special map to attributes.target.nodeValue || ''
rel: // Special map to attributes.ref.nodeValue || ''
}
Bây giờ cảnh báo lớn: Giống như tất cả các đối tượng Javascript , bạn có thể thêm các thuộc tính tùy chỉnh. Nhưng, những thứ đó sẽ không thay đổi bất cứ điều gì trên DOM. Bạn có thể làm:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Nhưng đó là giống như
newElement.myCustomDisplayAttribute = 'block';
Điều này có nghĩa là việc thêm một thuộc tính tùy chỉnh sẽ không được liên kết đến.attributes[attr].nodeValue
.
Hiệu suất
Tôi đã xây dựng trường hợp thử nghiệm jsperf để hiển thị sự khác biệt: https://jsperf.com/set-attribution-comparison . Về cơ bản, theo thứ tự:
dir
, id
, className
).element.attributes.ATTRIBUTENAME.nodeValue =
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Kết luận (TL; DR)
Sử dụng ánh xạ bất động sản đặc biệt từ HTMLElement
: element.dir
, element.id
, element.className
, hoặc element.lang
.
Nếu bạn chắc chắn 100% phần tử là phần mở rộng HTMLElement
có thuộc tính đặc biệt, hãy sử dụng ánh xạ đặc biệt đó. (Bạn có thể kiểm tra với if (element instanceof HTMLAnchorElement)
).
Nếu bạn chắc chắn 100% thuộc tính đã tồn tại, hãy sử dụng element.attributes.ATTRIBUTENAME.nodeValue = newValue
.
Nếu không, sử dụng setAttribute()
.
classList
được đảm bảo 100% để tồn tại, nhưng nó không phải là một thuộc tính chuỗi, nó là một DOMTokenList
đối tượng sống . Cài đặt .className
trực tiếp nhanh hơn thao tác classList
, nhưng bạn sẽ ghi đè lên toàn bộ.
.value
, bạn đang thay đổi giá trị bên trong của HTMLInputElement
, sau đó được phản ánh trên các thuộc tính. Họ cũng không cần phải như vậy string
. .valueAsNumber
sẽ thay đổi value
bên trong và string
hình thức của nó sẽ xuất hiện trong value
thuộc tính. developer.mozilla.org/en-US/docs/Web/HTML/Attribution
"Khi nào nên sử dụng setAttribution so với .attribution = trong JavaScript?"
Một quy tắc chung là sử dụng .attribute
và kiểm tra nếu nó hoạt động trên trình duyệt.
..Nếu nó hoạt động trên trình duyệt, bạn nên đi.
..Nếu không, sử dụng .setAttribute(attribute, value)
thay vì .attribute
cho thuộc tính đó .
Rửa sạch lặp lại cho tất cả các thuộc tính.
Vâng, nếu bạn lười biếng, bạn chỉ cần sử dụng .setAttribute
. Điều đó sẽ hoạt động tốt trên hầu hết các trình duyệt. (Mặc dù các trình duyệt hỗ trợ .attribute
có thể tối ưu hóa nó tốt hơn .setAttribute(attribute, value)
.)
Điều này trông giống như một trường hợp tốt hơn là sử dụng setAttribution:
Dev.Opera - JavaScript hiệu quả
var posElem = document.getElementById('animation');
var newStyle = 'background: ' + newBack + ';' +
'color: ' + newColor + ';' +
'border: ' + newBorder + ';';
if(typeof(posElem.style.cssText) != 'undefined') {
posElem.style.cssText = newStyle;
} else {
posElem.setAttribute('style', newStyle);
}
posElem.style = newStyle
hoạt động trong tất cả các trình duyệt (làm việc cho tôi trong Firefox)? Có phải chỉ vì lý do hiệu suất setAttribute
được ưa thích, tránh việc sơn lại? Là posElem.style.cssText = newStyle
nhiều nước hoa hơn sau đó posElem.style = newStyle
?
các phương thức để thiết lập các thuộc tính (ví dụ lớp) trên một phần tử: 1. el.groupName = chuỗi 2. el.setAttribution ('class', chuỗi) 3. el.attribut.setNamedItem (object) 4. el.setAttributionNode (nút)
Tôi đã thực hiện một bài kiểm tra điểm chuẩn đơn giản ( ở đây )
và có vẻ như setAttributionNode nhanh hơn khoảng 3 lần sau đó sử dụng setAttribution.
vì vậy nếu hiệu suất là một vấn đề - hãy sử dụng "setAttributionNode"
Điều thú vị từ tập lệnh Google API liên quan đến điều này:
Họ làm như thế này:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
Lưu ý, cách họ sử dụng setAttribute
cho "src" và "nonce", nhưng sau đó .async = ...
cho thuộc tính "async".
Tôi không chắc chắn 100%, nhưng có lẽ đó là vì "async" chỉ được hỗ trợ trên các trình duyệt hỗ trợ .attr =
gán trực tiếp . Vì vậy, sẽ không có ý nghĩa gì khi cố gắng sestAttribute("async")
vì nếu trình duyệt không hiểu .async=...
- nó sẽ không hiểu thuộc tính "async".
Hy vọng rằng, đó là một cái nhìn sâu sắc hữu ích từ dự án nghiên cứu "Un-minify GAPI" đang diễn ra của tôi . Sửa tôi nếu tôi sai.
.setAttribute()
sang[key] = value
, mọi thứ bắt đầu hoạt động kỳ diệu.