回答:
常に直接使用する必要があります .attribute
JavaScriptでプログラムによるアクセスが必要な場合は、形式を(ただし、以下のquirksmodeリンクを参照)。さまざまなタイプの属性( "onload"と考えてください)を正しく処理する必要があります。
DOMをそのまま扱いたい場合はgetAttribute
/を使用してくださいsetAttribute
(例:リテラルテキストのみ)。異なるブラウザは2つを混同します。Quirksモード:属性(非)互換性を参照してください。
Javascriptを:Definitive Guideの、それは物事を明確にしています。HTMLドキュメントのHTMLElementオブジェクトは、すべての標準HTML属性に対応するJSプロパティを定義することに注意してください。
したがってsetAttribute
、非標準の属性にのみ使用する必要があります。
例:
node.className = 'test'; // works
node.frameborder = '0'; // doesn't work - non standard attribute
node.setAttribute('frameborder', '0'); // works
node.frameborder
定義されているため、定義されていないため、値を取得するにはgetAttributeを使用する必要があります。
frameBorder
直接設定しても問題はありませんが、大文字の使用に注意してください。誰かが、HTMLの属性に相当するJavaScriptをキャメルケースに入れるのはおもしろいアイデアだと思っていました。私はこれについての仕様を見つけることができませんでしたが、ネットはそれが12の特定のケースの問題であることに同意しているようです(少なくともHTML 4の場合)。たとえば、次の投稿を参照してください:drupal.org/node/1420706#comment-6423420
usemap
画像のための動的マップを作成する場合、属性は、ドット表記法を使用して設定することができません。それimg.setAttribute('usemap', "#MapName");
はあなたの答えusemap
が「非標準」であることを意味しますか?
以前の回答はどれも完全ではなく、ほとんどが誤った情報を含んでいます。
DOMの属性へのアクセスの3つの方法があり要素は、JavaScriptでます。3つすべては、それらの使用方法を理解している限り、最新のブラウザーで確実に機能します。
element.attributes
要素は、プロパティ持つ属性ライブ返したNamedNodeMapのはAttrオブジェクトを。このコレクションのインデックスは、ブラウザによって異なる場合があります。したがって、順序は保証されません。NamedNodeMap
属性を追加および削除するためのメソッドがあります(それぞれgetNamedItem
およびsetNamedItem
)。
XMLでは明示的に大文字と小文字が区別されますが、DOM仕様では文字列名を正規化する必要があるため、渡される名前ではgetNamedItem
大文字と小文字が区別されないことに注意してください。
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
これらのメソッドはに直接存在し、そのメソッドElement
にアクセスする必要はありませんがattributes
、同じ機能を実行します。
ここでも、文字列名は大文字と小文字を区別しないことに注意してください。
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
DOMオブジェクトの便利なプロパティを使用して、多くの属性にアクセスできます。存在する属性は、HTMLで定義されている属性ではなく、DOMノードのタイプによって異なります。プロパティは、問題のDOMオブジェクトのプロトタイプチェーンのどこかに定義されています。定義される特定のプロパティは、アクセスする要素のタイプによって異なります。たとえば、className
およびid
は、Element
要素であるすべてのDOMノードに定義され、存在します(つまり、テキストまたはコメントノードではありません)。しかしvalue
、より狭いです。それHTMLInputElement
は他の要素で定義され、存在しない場合があります。
JavaScriptプロパティでは大文字と小文字が区別されることに注意してください。ほとんどのプロパティは小文字を使用しますが、いくつかはキャメルケースです。したがって、必ず仕様を確認してください。
この「チャート」は、これらのDOMオブジェクトのプロトタイプチェーンの一部をキャプチャします。それは完全に近いものではありませんが、全体的な構造を捉えています。
____________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>
警告:これは、HTML仕様がどのように定義し、最新のブラウザーが属性を処理するかを説明したものです。私は古代の壊れたブラウザの制限に対処しようとはしませんでした。古いブラウザをサポートする必要がある場合は、この情報に加えて、それらのブラウザで何が壊れているかを知る必要があります。
setAttribute
対応するプロパティがないため、ARIA属性を変更する場合に必要となる1つのケースが見つかりました。例えば
x.setAttribute('aria-label', 'Test');
x.getAttribute('aria-label');
そのx.arialabel
ようなものはないので、setAttributeを使用する必要があります。
編集:x ["aria-label"]は機能しません。本当に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"
これらの回答は、プロパティと属性の間の大きな混乱に実際には対処していません。また、JavaScriptプロトタイプによっては、要素のプロパティを使用して属性にアクセスできる場合とできない場合があります。
まず、HTMLElement
はJavaScriptオブジェクトであることを覚えておく必要があります。すべてのオブジェクトと同様に、それらにはプロパティがあります。確かに、内部にあるほぼすべての名前のプロパティを作成できますHTMLElement
が、DOM(ページ上にあるもの)に対して何もする必要はありません。ドット表記(.
)はプロパティ用です。現在、属性にマップされているいくつかの特別なプロパティがあり、現時点または書き込み時には、保証されているのは4つだけです(詳細は後ほど)。
すべてHTMLElement
のには、というプロパティが含まれていますattributes
。DOMの要素に関連HTMLElement.attributes
するライブ NamedNodeMap
オブジェクトです。「ライブ」とは、ノードがDOMで変更されると、JavaScript側で変更され、その逆も同様です。この場合、DOM属性は問題のノードです。AにNode
は、.nodeValue
変更可能なプロパティがあります。NamedNodeMap
オブジェクトには、setNamedItem
ノード全体を変更できる場所と呼ばれる関数があります。キーを使用してノードに直接アクセスすることもできます。たとえば、.attributes["dir"]
どちらが.attributes.getNamedItem('dir');
(サイドノート、NamedNodeMap
大文字と小文字を区別しないので、を渡すこともできます'DIR'
)と同じと言うことができます。
同様の機能は直接ありますHTMLElement
あなただけを呼び出すことができる場所setAttribute
であろう、自動的にノードを作成し、それが存在し、設定されていない場合nodeValue
。などの特別なプロパティを介してプロパティとして直接アクセスできるいくつかの属性もあります。これがどのように見えるかの大まかなマッピングは次のとおりです。HTMLElement
dir
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 || ''
}
したがって、dir
6つの方法で属性を変更できます。
// 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';
あなたはだけ、方法#1-5とのすべてのプロパティを更新することができdir
、id
、lang
、およびclassName
メソッドの#6で。
HTMLElement
これらの4つの特別なプロパティがあります。一部の要素は拡張クラスでHTMLElement
あり、さらにマッピングされたプロパティがあります。たとえば、HTMLAnchorElement
持ってHTMLAnchorElement.href
、HTMLAnchorElement.rel
とHTMLAnchorElement.target
。しかし、注意してくださいあなたは(上のように、これらの特殊な性質を持っていない要素にこれらのプロパティを設定した場合、HTMLTableElement
)その後、属性が変更されていないと、彼らはただ、通常のカスタムプロパティです。よりよく理解するために、その継承の例を次に示します。
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 || ''
}
大きな警告:すべてのJavaScriptオブジェクトと同様に、カスタムプロパティを追加できます。しかし、それらはDOMで何も変更しません。できるよ:
const newElement = document.createElement('div');
// THIS WILL NOT CHANGE THE ATTRIBUTE
newElement.display = 'block';
しかし、それは同じです
newElement.myCustomDisplayAttribute = 'block';
つまり、カスタムプロパティの追加はにリンクされません.attributes[attr].nodeValue
。
パフォーマンス
違いを示すjsperfテストケースを作成しました:https ://jsperf.com/set-attribute-comparison 。基本的に、順番に:
dir
、id
、className
)。element.attributes.ATTRIBUTENAME.nodeValue =
element.attributes.getNamedItem(ATTRIBUTENAME).nodeValue = newValue
element.attributes.ATTRIBUTENAME = newNode
element.attributes.setNamedItem(ATTRIBUTENAME) = newNode
結論(TL; DR)
から特別なプロパティのマッピングを使用しますHTMLElement
:element.dir
、element.id
、 element.className
、またはelement.lang
。
100%の場合、要素は拡張されています HTMLElement
特別なプロパティでているその特別なマッピングを使用します。(で確認できますif (element instanceof HTMLAnchorElement)
)。
属性がすでに存在することを100%確信している場合は、 element.attributes.ATTRIBUTENAME.nodeValue = newValue
。
そうでない場合は、を使用してくださいsetAttribute()
。
classList
100%存在することが保証されていますが、これは文字列プロパティではなく、ライブDOMTokenList
オブジェクトです。.className
直接設定することは、を操作するよりも高速classList
ですが、全体を上書きすることになります。
.value
すると、の内部値が変更HTMLInputElement
され、属性に反映されます。彼らはまたする必要はありませんstring
。内部で.valueAsNumber
変更され、そのフォームが属性に表示されます。 developer.mozilla.org/en-US/docs/Web/HTML/Attributesvalue
string
value
「JavaScriptでsetAttributeと.attribute =を使用する場合」
一般的なルールは .attribute
、ブラウザで動作するかどうかして確認することです。
..それがブラウザーで動作する場合は、問題ありません。
それは、使用していません..If .setAttribute(attribute, value)
の代わりを.attribute
するためにその属性。
すべての属性のすすぎを繰り返します。
まあ、もしあなたが怠惰なら、あなたは単に使うことができます.setAttribute
。ほとんどのブラウザで問題なく動作するはずです。(ただし、をサポート.attribute
するブラウザはを最適化できます.setAttribute(attribute, value)
。)
これは、setAttributeを使用する方がよい1つのケースのように見えます。
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
すべてのブラウザで動作ない(Firefoxで動作した)setAttribute
再描画を避けて、パフォーマンス上の理由からだけですか?でposElem.style.cssText = newStyle
、より多くのperfomrant posElem.style = newStyle
?
要素の属性(クラスなど)を設定するためのメソッド:1. el.className = string 2. el.setAttribute( 'class'、string)3. el.attributes.setNamedItem(object)4. el.setAttributeNode(node)
簡単なベンチマークテストを行いました(ここで)
そして、setAttributeNodeはsetAttributeを使用するよりも約3倍速いようです。
パフォーマンスに問題がある場合-「setAttributeNode」を使用してください
からの興味深いテイクアウト Google APIスクリプトこれに関する:
彼らはこのようにします:
var scriptElement = document.createElement("script");
scriptElement = setAttribute("src", "https://some.com");
scriptElement = setAttribute("nonce", "https://some.com");
scriptElement.async = "true";
注意、彼らがどのように使うか setAttribute
「src」と「nonce」.async = ...
、「async」属性。
100%確信はありませんが、おそらく「非同期」はダイレクトをサポートするブラウザでのみサポートされているためです .attr =
割り当てです。したがって、sestAttribute("async")
ブラウザが理解しない場合、.async=...
「非同期」属性を理解しないため、試行しても意味がありません。
うまくいけば、それは私の進行中の「Un-minify GAPI」研究プロジェクトからの有用な洞察です。私が間違っていたら訂正してください。
.setAttribute()
と[key] = value
、すべてが魔法のように機能し始めました。