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
/ setAttribute
ketika 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 setAttribute
atribut non-standar.
Contoh:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborder
TIDAK didefinisikan, jadi Anda harus mendapatkanAttribute untuk mendapatkan kembali nilainya.
frameBorder
secara 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
usemap
atribut tidak dapat diatur menggunakan notasi dot saat membuat peta dinamis untuk gambar. Membutuhkan img.setAttribute('usemap', "#MapName");
Apakah jawaban Anda menyiratkan bahwa usemap
oleh 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.attributes
Elemen memiliki atribut properti yang mengembalikan NamedNodeMap langsung dari objek Attr . Indeks koleksi ini mungkin berbeda di antara peramban. Jadi, pesanannya tidak dijamin. NamedNodeMap
memiliki metode untuk menambah dan menghapus atribut ( getNamedItem
dan 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 getNamedItem
tidak 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.setAttribute
Metode ini ada langsung di Element
tanpa perlu mengakses attributes
dan 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.id
Banyak 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, className
dan id
didefinisikan Element
dan ada pada semua node DOM yang merupakan elemen (mis. Bukan teks atau komentar). Tapivalue
lebih sempit. Ini didefinisikan HTMLInputElement
dan 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 setAttribute
diperlukan 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 HTMLElement
adalah 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 HTMLElement
termasuk properti yang disebut attributes
. HTMLElement.attributes
adalah 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 Node
memiliki .nodeValue
properti yang dapat Anda ubah. NamedNodeMap
objek memiliki fungsi yang disebut di setNamedItem
mana 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, NamedNodeMap
tidak peka huruf besar-kecil, sehingga Anda juga dapat lulus 'DIR'
);
Ada fungsi serupa langsung di HTMLElement
mana Anda bisa memanggil setAttribute
yang secara otomatis akan membuat simpul jika tidak ada dan mengatur nodeValue
. Ada juga beberapa atribut yang dapat Anda akses langsung sebagai properti HTMLElement
melalui 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 dir
atribut 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 className
dengan metode # 6.
HTMLElement
memiliki 4 sifat khusus tersebut. Beberapa elemen adalah kelas yang diperluas yang HTMLElement
memiliki lebih banyak properti yang dipetakan. Misalnya, HTMLAnchorElement
memiliki 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 = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
Kesimpulan (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()
.
classList
dijamin 100% ada, tapi ini bukan properti string, ini DOMTokenList
objek langsung . Pengaturan .className
secara 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
. .valueAsNumber
akan berubah secara value
internal , dan string
formulir itu akan muncul di value
atribut. developer.mozilla.org/en-US/docs/Web/HTML/Attributes
"Kapan menggunakan setAttribute vs .attribute = dalam JavaScript?"
Aturan umum adalah untuk menggunakan .attribute
dan memeriksa apakah itu berfungsi di browser.
..Jika itu bekerja di browser, Anda baik untuk pergi.
..Jika tidak, gunakan .setAttribute(attribute, value)
bukan .attribute
untuk 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 .attribute
dapat 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 = newStyle
berfungsi di semua browser (berfungsi untuk saya di Firefox)? Apakah hanya karena alasan kinerja yang setAttribute
lebih disukai, menghindari pengecatan ulang? Apakah posElem.style.cssText = newStyle
lebih 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 setAttribute
untuk "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.