Jawaban:
Anda harus selalu menggunakan direct .attribute formulir (tetapi lihat tautan quirksmode di bawah) jika Anda ingin akses terprogram dalam JavaScript. Itu harus menangani berbagai jenis atribut (pikirkan "membebani") dengan benar.
Gunakan getAttribute/ setAttributeketika Anda ingin berurusan dengan DOM sebagaimana adanya (mis. Hanya teks literal). Browser yang berbeda membingungkan keduanya. Lihat mode Quirks: kompatibilitas atribut (dalam) .
Dari Javascript: The Definitive Guide , ini menjelaskan berbagai hal. Ini mencatat bahwa objek HTMLElement dari dokumen HTML mendefinisikan properti JS yang sesuai dengan semua atribut HTML standar.
Jadi, Anda hanya perlu menggunakan setAttributeatribut non-standar.
Contoh:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborderTIDAK didefinisikan, jadi Anda harus mendapatkanAttribute untuk mendapatkan kembali nilainya.
frameBordersecara langsung, tetapi perhatikan kapitalisasi. Seseorang berpikir itu adalah ide yang sangat bagus untuk menambahkan persamaan JavaScript pada atribut HTML. Saya belum berhasil menemukan spesifikasi untuk ini, tetapi internet tampaknya setuju bahwa ini adalah masalah 12 kasus tertentu (setidaknya untuk HTML 4). Lihat misalnya posting berikut: drupal.org/node/1420706#comment-6423420
usemapatribut tidak dapat diatur menggunakan notasi dot saat membuat peta dinamis untuk gambar. Membutuhkan img.setAttribute('usemap', "#MapName");Apakah jawaban Anda menyiratkan bahwa usemapoleh karena itu "tidak standar"?
Tidak ada jawaban sebelumnya yang lengkap dan sebagian besar berisi informasi yang salah.
Ada tiga cara mengakses atribut Elemen DOM dalam JavaScript. Ketiganya bekerja dengan andal di peramban modern selama Anda mengerti cara menggunakannya.
element.attributesElemen memiliki atribut properti yang mengembalikan NamedNodeMap langsung dari objek Attr . Indeks koleksi ini mungkin berbeda di antara peramban. Jadi, pesanannya tidak dijamin. NamedNodeMapmemiliki metode untuk menambah dan menghapus atribut ( getNamedItemdan setNamedItem, masing-masing).
Perhatikan bahwa meskipun XML secara eksplisit peka terhadap huruf besar-kecil, spesifikasi DOM meminta nama string untuk dinormalisasi , sehingga nama yang diteruskan menjadi getNamedItemtidak sensitif huruf besar-kecil.
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.setAttributeMetode ini ada langsung di Elementtanpa perlu mengakses attributesdan metodenya tetapi melakukan fungsi yang sama.
Sekali lagi, perhatikan bahwa nama string tidak sensitif huruf.
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.idBanyak atribut dapat diakses menggunakan properti yang mudah digunakan pada objek DOM. Atribut mana yang ada tergantung pada jenis simpul DOM, bukan atribut mana yang didefinisikan dalam HTML. Properti didefinisikan di suatu tempat di rantai prototipe objek DOM yang bersangkutan. Properti spesifik yang ditentukan akan tergantung pada jenis Elemen yang Anda akses. Misalnya, classNamedan iddidefinisikan Elementdan ada pada semua node DOM yang merupakan elemen (mis. Bukan teks atau komentar). Tapivalue lebih sempit. Ini didefinisikan HTMLInputElementdan mungkin tidak ada pada elemen lain.
Perhatikan bahwa properti JavaScript peka huruf besar-kecil. Meskipun sebagian besar properti akan menggunakan huruf kecil, beberapa camelCase. Jadi selalu periksa spek untuk memastikan.
"Bagan" ini menangkap sebagian rantai prototipe untuk objek DOM ini. Bahkan tidak hampir selesai, tetapi ia menangkap keseluruhan struktur.
____________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>
Peringatan: Ini adalah penjelasan tentang bagaimana spesifikasi HTML mendefinisikan dan browser modern menangani atribut. Saya tidak mencoba untuk berurusan dengan batasan dari browser yang rusak dan kuno. Jika Anda perlu mendukung browser lama, selain informasi ini, Anda perlu tahu apa yang rusak di browser tersebut.
Satu kasus yang saya temukan di mana setAttributediperlukan adalah ketika mengubah atribut ARIA, karena tidak ada properti yang sesuai. Sebagai contoh
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
Tidak ada x.arialabel atau semacamnya, jadi Anda harus menggunakan setAttribute.
Sunting: x ["label aria"] tidak berfungsi . Anda benar-benar membutuhkan setAttribute.
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"
Jawaban ini tidak benar-benar mengatasi kebingungan besar antara properti dan atribut . Juga, tergantung pada prototipe Javascript, terkadang Anda dapat menggunakan properti elemen untuk mengakses atribut dan terkadang Anda tidak bisa.
Pertama, Anda harus ingat bahwa objek HTMLElementadalah Javascript. Seperti semua objek, mereka memiliki properti. Tentu, Anda dapat membuat properti yang disebut hampir semua yang Anda inginkan di dalamnya HTMLElement, tetapi tidak harus melakukan apa pun dengan DOM (apa yang ada di halaman). Notasi titik ( .) adalah untuk properti . Sekarang, ada beberapa properti khusus yang dipetakan ke atribut, dan pada saat itu atau tulisan hanya ada 4 yang dijamin (lebih lanjut tentang itu nanti).
Semua HTMLElementtermasuk properti yang disebut attributes. HTMLElement.attributesadalah Obyek hidup NamedNodeMap yang berkaitan dengan unsur-unsur dalam DOM. "Langsung" berarti bahwa ketika node berubah di DOM, mereka berubah di sisi JavaScript, dan sebaliknya. Atribut DOM, dalam hal ini, adalah simpul yang dimaksud. A Nodememiliki .nodeValueproperti yang dapat Anda ubah. NamedNodeMapobjek memiliki fungsi yang disebut di setNamedItemmana Anda dapat mengubah seluruh node. Anda juga dapat langsung mengakses simpul dengan kunci. Misalnya, Anda dapat mengatakan .attributes["dir"]yang sama dengan .attributes.getNamedItem('dir');(Catatan samping, NamedNodeMaptidak peka huruf besar-kecil, sehingga Anda juga dapat lulus 'DIR');
Ada fungsi serupa langsung di HTMLElementmana Anda bisa memanggil setAttributeyang secara otomatis akan membuat simpul jika tidak ada dan mengatur nodeValue. Ada juga beberapa atribut yang dapat Anda akses langsung sebagai properti HTMLElementmelalui properti khusus , seperti dir. Berikut ini pemetaan kasar dari tampilannya:
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 || ''
}
Jadi, Anda dapat mengubah diratribut 6 cara:
// 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';
Anda dapat memperbarui semua properti dengan metode # 1-5, tetapi hanya dir, id, lang, dan classNamedengan metode # 6.
HTMLElementmemiliki 4 sifat khusus tersebut. Beberapa elemen adalah kelas yang diperluas yang HTMLElementmemiliki lebih banyak properti yang dipetakan. Misalnya, HTMLAnchorElementmemiliki HTMLAnchorElement.href, HTMLAnchorElement.rel, dan HTMLAnchorElement.target. Namun, berhati-hatilah , jika Anda menyetel properti tersebut pada elemen yang tidak memiliki properti khusus itu (seperti pada a HTMLTableElement) maka atribut tidak berubah dan itu hanya, properti kustom normal. Untuk lebih memahami, inilah contoh warisannya:
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 || ''
}
Sekarang peringatan besar: Seperti semua objek Javascript , Anda dapat menambahkan properti khusus. Tapi, itu tidak akan mengubah apa pun pada DOM. Anda dapat melakukan:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
Tapi itu sama dengan
newElement.myCustomDisplayAttribute = 'block';
Ini berarti bahwa menambahkan properti khusus tidak akan ditautkan ke.attributes[attr].nodeValue .
Performa
Saya telah membangun test case jsperf untuk menunjukkan perbedaannya: https://jsperf.com/set-attribute-comparison . Pada dasarnya, Agar:
dir, id, className).element.attributes.ATTRIBUTENAME.nodeValue = element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValueelement.attributes.ATTRIBUTENAME = newNode element.attributes.setNamedItem(ATTRIBUTENAME) = newNodeKesimpulan (TL; DR)
Gunakan pemetaan properti khusus dari HTMLElement: element.dir,element.id , element.className, atau element.lang.
Jika Anda 100% yakin elemennya adalah extended HTMLElement dengan properti khusus, gunakan pemetaan khusus itu. (Anda dapat memeriksanya if (element instanceof HTMLAnchorElement)).
Jika Anda 100% yakin atributnya sudah ada, gunakan element.attributes.ATTRIBUTENAME.nodeValue = newValue.
Jika tidak, gunakan setAttribute().
classListdijamin 100% ada, tapi ini bukan properti string, ini DOMTokenListobjek langsung . Pengaturan .classNamesecara langsung lebih cepat daripada memanipulasi classList, tetapi Anda akan menimpa semuanya.
.value, Anda mengubah internal yang nilai HTMLInputElement, yang kemudian tercermin pada atribut. Mereka juga tidak harus seperti itu string. .valueAsNumberakan berubah secara value internal , dan stringformulir itu akan muncul di valueatribut. developer.mozilla.org/en-US/docs/Web/HTML/Attributes
"Kapan menggunakan setAttribute vs .attribute = dalam JavaScript?"
Aturan umum adalah untuk menggunakan .attributedan memeriksa apakah itu berfungsi di browser.
..Jika itu bekerja di browser, Anda baik untuk pergi.
..Jika tidak, gunakan .setAttribute(attribute, value)bukan .attributeuntuk yang atribut.
Bilas-ulangi untuk semua atribut.
Nah, jika Anda malas Anda cukup menggunakan .setAttribute. Itu seharusnya bekerja dengan baik pada sebagian besar browser. (Meskipun browser yang mendukung .attributedapat mengoptimalkannya lebih baik daripada .setAttribute(attribute, value).)
Ini terlihat seperti satu kasus di mana lebih baik menggunakan setAttribute:
Dev.Opera - JavaScript yang Efisien
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 = newStyleberfungsi di semua browser (berfungsi untuk saya di Firefox)? Apakah hanya karena alasan kinerja yang setAttributelebih disukai, menghindari pengecatan ulang? Apakah posElem.style.cssText = newStylelebih banyak perfomran posElem.style = newStyle?
metode untuk menetapkan atribut (misalnya kelas) pada elemen: 1. el.className = string 2. el.setAttribute ('class', string) 3. el.attributes.setNamedItem (objek) 4. el.setAttributeNode (node)
Saya telah membuat tes benchmark sederhana ( di sini )
dan tampaknya setAttributeNode sekitar 3 kali lebih cepat daripada menggunakan setAttribute.
jadi jika kinerja merupakan masalah - gunakan "setAttributeNode"
Pengambilan yang menarik dari skrip Google API mengenai hal ini:
Mereka melakukannya seperti ini:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
Perhatikan, bagaimana mereka digunakan setAttributeuntuk "src" dan "nonce", tapi kemudian.async = ... atribut untuk atribut "async".
Saya tidak 100% yakin, tapi mungkin itu karena "async" hanya didukung di browser yang mendukung .attr =penugasan langsung . Jadi, tidak masuk akal mencoba sestAttribute("async")karena jika browser tidak mengerti.async=... - itu tidak akan mengerti atribut "async".
Semoga itu adalah wawasan bermanfaat dari proyek penelitian "Un-minify GAPI" saya yang sedang berlangsung . Koreksi saya jika saya salah.
.setAttribute()ke[key] = value, semuanya mulai bekerja secara ajaib.