DOM の中国語名は文書オブジェクトモデル、英語名は Document Object Model で、略して DOM と呼ばれます。これは html と xml 文書に対する API であり、html を木構造で表現することで、文書構造をより直感的に研究することができます。この木構造の文書構造を DOM ツリーまたはノードツリーと呼びます。同じ概念です。
一、DOM とは何ですか?#
DOM の中国語名は文書オブジェクトモデル、英語名は Document Object Model で、略して DOM と呼ばれます。これは html と xml 文書に対する API であり、html を木構造で表現することで、文書構造をより直感的に研究することができます。この木構造の文書構造を DOM ツリーまたはノードツリーと呼びます。同じ概念です。
js は dom ノードを通じて、文書の html タグ、属性、css スタイル、および具体的な内容を変更し、ページ内のすべてのイベントに応答することができます。
二、ノードツリー#
1. ノードタイプ#
- 文書ノード--Document
- タグノード--Element
- テキストノード--Text
- コメントノード--Comment
- 属性ノード--Attr
2. 属性#
- ノードタイプ--nodeType
- ノード名--nodeName
- ノード値--nodeValue
- 子ノード--childNodes
- 親ノード--parentNodes
- 前のノード--previousSibling
- 次のノード--nextSibling
- 最初の子ノード--firstChild
- 最後の子ノード--lastChild
3. 文書ノード--document#
(1) 取得#
- getElementById ()--id で要素を取得
<div id="demo">idで要素を取得</div>
<script>
var demo = document.getElementById('demo');
demo.onclick = function() {
console.log('idで要素を取得')
}
</script>
<!-- idがdemoの要素をクリックすると、コンソールに' idで要素を取得'と出力されます -->
- getElementsByName ()--name で要素を取得
<input type="text" name="int" value="nameで要素を取得1">
<input type="text" name="int" value="nameで要素を取得2">
<script>
var int = document.getElementsByName('int');
for(var i = 0;i < int.length; i++) {
console.log(int[i].value);
}
</script>
<!-- コンソールにnameがintの要素のvalue値が出力されます -->
- getElementsByTagName ()--タグ名で要素を取得
<div>タグ名で要素を取得1</div>
<div>タグ名で要素を取得2</div>
<script>
var div = document.getElementsByTagName('div');
for(var i = 0;i < div.length; i++) {
console.log(div[i].innerHTML)
}
</script>
<!-- コンソールにタグ名がdivの要素のテキスト内容が出力されます -->
- getElementsByClassName ()--class で要素を取得
<div class="demo">classで要素を取得1</div>
<div class="demo">classで要素を取得2</div>
<script>
var demo = document.getElementsByClassName('demo');
for(var i = 0;i < demo.length; i++) {
console.log(demo[i].innerHTML)
}
</script>
<!-- コンソールにclassがdemoの要素のテキスト内容が出力されます -->
- querySelector ()--セレクタで要素を取得
querySelector () の括弧の中には記号を付ける必要があります。classは.
、idは#
、タグはそのままタグ名TagName
を書きます。
<div>セレクタでタグ名を取得</div>
<div class="div">セレクタでclassを取得</div>
<div id="div">セレクタでidを取得</div>
<script>
var divtag = document.querySelector('div');
var divclass = document.querySelector('.div');
var divid = document.querySelector('#div');
divtag.onclick = function() {
console.log('セレクタでタグ名を取得')
};
// タグdivをクリックすると、コンソールに"セレクタでタグ名を取得"と出力されます
divclass.onclick = function() {
console.log('セレクタでclassを取得')
};
// classがdivをクリックすると、コンソールに"セレクタでclassを取得"と出力されます
divid.onclick = function() {
console.log('セレクタでidを取得')
};
// idがdivをクリックすると、コンソールに"セレクタでidを取得"と出力されます
</script>
- querySelectorAll ()--セレクタで要素集合を取得
取得されるのは配列の集合です。
<input type="text" value="int1">
<input type="text" value="int2">
<input type="text" value="int3">
<script>
var int = document.querySelectorAll('input')
for(i = 0; i < int.length; i++) {
console.log(int[i].value)
}
</script>
<!-- ブラウザは順に`int1`,`int2`,`int3`を出力します -->
(2) 作成#
- createElement ()--要素(タグ)ノードを作成
<ul id="ul"></ul>
<script>
var ul = document.getElementById('ul');
ul.appendChild(document.createElement('li'))
</script>
ul の下に li タグが生成されたことが確認できます。
- createTextNode ()--テキストノードを作成
<ul id="ul"></ul>
<script>
var ul = document.getElementById('ul');
var li = ul.appendChild(document.createElement('li'));
var node = document.createTextNode('私はliです');
li.appendChild(node);
</script>
li タグの中にテキストが生成されました。
- createAttribute ()--属性ノードを作成
<input type="text">
<script>
var int = document.getElementsByTagName('input')[0];
var value = document.createAttribute('value');
value.nodeValue = '属性ノードを作成して生成';
int.setAttributeNode(value);
</script>
value 属性値が正常に作成されたことが確認できます。
- createComment ()--コメントノードを作成
<div id="div">コメントノードを作成</div>
<script>
var div = document.getElementById('div');
var comment = document.createComment('コメントノードを追加');
div.appendChild(comment);
</script>
f12 でソースコードを確認すると、div に 1 行のコメントが生成されていることがわかります。
- createDocumentFragment ()--文書フラグメントを作成
文書フラグメントの役割は、追加されたすべてのノードの親要素に相当します。
- createDocumentFragment がなければ、多くのノードを追加しても、dom 上に表示されますが、追加するたびに appendChild () メソッドが呼び出され、多くのページレンダリングが発生し、冗長に見えます。
- 複数の追加ノードを createDocumentFragment ノードの中に置くと、ページは 1 回だけ呼び出してすべてのノードをレンダリングできます。
-
createEvent ()--イベントオブジェクトを作成
-
addEventListener ()--イベントリスナー関数を追加
-
removeEventListener ()--イベントリスナー関数を削除
- dispatchEvent ()--イベントを発火
CSS 操作#
<div id="demo">dom</div>
<script>
// 直接'.'を使ってstyleを操作
var demo= document.getElementById('demo');
demo.style.color = 'red';
// setAttribute()を使って属性ノードを作成
demo.setAttribute('style','background-color: green');
// styleのcssText属性を使って
demo.style.cssText = "border: 10px solid black";
</script>
4. 要素ノード(element オブジェクト)#
innerHTML, innerText, outerHTML, outerText の違いについて
一つは要素の内容、もう一つはテキストの内容です。
<div id="div1">最初のdiv</div>
<div id="div2">二番目のdiv</div>
<div id="div3">三番目のdiv</div>
<div id="div4">四番目のdiv</div>
<div id="div5"></div>
<div id="div6"></div>
<div id="div7"></div>
<div id="div8"></div>
<script>
var div1 = document.getElementById('div1').innerHTML
console.log(div1) // 最初のdiv
var div1 = document.getElementById('div1').outerHTML
console.log(div1) // <div id="div1">最初のdiv</div>
var div2 = document.getElementById('div2').innerText
console.log(div2) // 二番目のdiv
var div2 = document.getElementById('div2').outerText
console.log(div2) // 二番目のdiv
document.getElementById('div5').innerHTML = '<a>《第5のdiv》</a>'
// 既存のタグ内に内容を追加し、タグがあれば認識されます
document.getElementById('div6').outerHTML = '<a>《第6のdiv》</a>'
// 元のタグが上書きされ、新しいテキストにタグが含まれていれば自動的に生成され、タグがなければそのままテキストとして表示されます
document.getElementById('div7').innerText = '<a>《第7のdiv》</a>'
// 既存のタグ内に内容を追加し、新しいタグはタグ要素として認識されず、元のタグ内にテキスト内容として直接書き込まれます
document.getElementById('div8').outerText = '<a>《第8のdiv》</a>'
// 元のタグが上書きされ、新しいタグはタグ要素として認識されず、直接テキスト形式で表示されます
</script>
(1) ノード属性#
- childElementCount--現在の要素の子ノードの数を返します。
<div id="demo">
<a></a>
<span></span>
<p></p>
<div></div>
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.childElementCount) // 4
</script>
- firstElementChild--現在の要素の最初の子要素ノードを返します。
lastElementChild--現在の要素の最後の子要素ノードを返します。
<div id="demo">
<a></a>
<span></span>
<p></p>
<div></div>
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.firstElementChild) // <a></a>
console.log(demo.lastElementChild) // <div></div>
</script>
- nextElementSibling--現在の要素の次の兄弟要素ノードを返します。
previousElementSibling--現在の要素の前の兄弟要素ノードを返します。
<span></span>
<div id="demo"></div>
<p></p>
<script>
var demo = document.getElementById('demo')
console.log(demo.nextElementSibling) // <p></p>
console.log(demo.previousElementSibling) // <span></span>
</script>
- 現在の要素のすべての子ノードを返します。
<div id="demo">
<span></span>
<p></p>
<a></a>
</div>
<script>
var demo = document.getElementById('demo').children
for(var i in demo) {
console.log(demo[i])
}
</script>
コンソールで返された結果を確認します。
- すべての子ノード集合を返します。
<div id="demo">
<span></span>
<p></p>
<a id="demo1"></a>
</div>
<script>
var demo = document.getElementById('demo').children
for(var i in demo1.childNodes) {
console.log(demo[i])
}
</script>
(2) ノードメソッド#
- appendChild--子ノードを挿入
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('子ノードを挿入')
demo.appendChild(node)
</script>
f12 で確認すると、div にノードが挿入されていることがわかります。
- insertBefore (a, b)--指定位置にノードを挿入
パラメータ a は挿入する内容、b は位置を指定し、b ノードの前に a ノードを挿入します。
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('子ノードを挿入')
demo.appendChild(node)
var hr = document.createElement('hr')
demo.insertBefore(hr, node)
</script>
元のテキストノードの前に新しい要素ノードが追加されたことが確認できます。
- replaceChild (a, b)--ノードを置き換える
パラメータ a でパラメータ b を置き換え、a は新しいノード、b は古いノードを示します。
<div id="demo"></div>
<script>
var demo = document.getElementById('demo')
var node = document.createTextNode('子ノードを挿入')
demo.appendChild(node)
var h3 = document.createElement('h3')
var h3node = document.createTextNode('タイトル')
h3.appendChild(h3node)
demo.replaceChild(h3, node)
</script>
h3
は新しいノード、node
は古いノードで、画像から見ると b が a を置き換え、成功したことがわかります。
- removeChild--親ノードが子ノードを削除
<div id="demo">
<div id="son"></div>
</div>
<script>
var demo = document.getElementById('demo')
var son = document.getElementById('son')
demo.removeChild(son)
</script>
f12 で確認すると、id が son の要素ノードがdemo.removeChild()
によって削除されたことがわかります。
- removeAttribute--属性ノードを削除
<div id="demo" class="div"></div>
<script>
var demo = document.getElementById('demo')
demo.removeAttribute('class')
</script>
class 属性が削除されたことが確認できます。
- テキストノードを削除
<div id="demo">テキスト</div>
<script>
var demo = document.getElementById('demo')
demo.removeChild(demo.childNodes[0])
</script>
demo.childNodes[0]
で demo の最初のノード、つまりテキストノードを取得し、removeChild
で削除します。
- isEqualNode--二つの要素が
等しい
かどうかを判断
isSameNode--二つの要素が同じ
かどうかを判断
二つはそれぞれ
等しい
と同じ
を表します。
(1) isEqualNode
の等しいは、二つのノードが同じタイプで、等しい属性(nodeName, nodeValue など)を持ち、attributes や childNodes も等しい(等しい位置に同じ値が含まれる)ことを指します。
(2) isSameNode
の同じは、二つのノードが同じオブジェクトを参照していることを指します。
<form action="#">
<input type="button" />
</form>
<form action="#">
<input type="button" />
</form>
<form action="#" id="o">
<input type="button" />
</form>
<form action="#" id="o">
<input type="text" />
</form>
<script>
var forms = document.forms;
var form1 = forms[0];
var form2 = forms[1];
var form3 = forms[2];
var form4 = forms[3];
var _form1 = document.querySelectorAll('form')[0];
console.log(form1.isSameNode(form1)) //true 二つのノードが同じオブジェクトを参照しています
console.log(form1.isSameNode(_form1)) //true 二つのノードが同じオブジェクトを参照しています
console.log(form1.isSameNode(form2)) //false 二つのノードが同じオブジェクトを参照していません
console.log(form1.isEqualNode(form2)) //true 二つのノードが完全に等しい属性を持っています
console.log(form1.isEqualNode(form3)) //false form1には等しいid属性がありません
console.log(form3.isEqualNode(form4)) //false form4のchildNodesのinputはtextタイプで、form3とは異なります
</script>
例のコードから違いがわかります:
(1) isSameNode
は同じオブジェクトを参照している場合のみ同じで、二つの方法で同じオブジェクトを呼び出し、比較しても同じオブジェクトであるため、同じです。
(2) isEqualNode
は二つのオブジェクトの要素ノードが等しいかどうかを比較し、一致すれば等しい true となります。
- hasChildNodes ()--要素が子ノードを持っているかどうかを判断
demo
が子ノードを持っているかどうかを判断し、その子ノードを出力します。
<div id="demo">
<!-- <a></a> -->
</div>
<script>
var demo = document.getElementById('demo')
console.log(demo.hasChildNodes())
console.log(demo.childNodes)
</script>
- contains (a)--指定された子ノード(パラメータ a)を含むかどうかを判断
id="a"
の要素が存在するため、contains は成功しtrue
を出力します。
id="b"
の要素は存在しないため、false
が出力されます。
<div id="demo">
<a id="a"></a>
<a></a>
</div>
<script>
var demo = document.getElementById('demo')
var a = document.getElementById('a')
console.log(demo.contains(a)) // true
var b = document.getElementById('b')
console.log(demo.contains(b)) // false
</script>
5. 属性ノード(Attr オブジェクト)#
<input type="text" id="int">
<script>
var int = document.getElementById('int')
// 1.属性値を取得
console.log(int.getAttribute("type"))
// text
// 2.属性ノードを取得
console.log(int.getAttributeNode("type"))
// type="text"
// 3.属性値を設定
int.setAttribute("value", "inputボックス")
// <input type="text" id="int" value="inputボックス">
// 4.属性ノードを設定
let name = document.createAttribute("name");
name.nodeValue = "uname";
int.setAttributeNode(name);
console.log(int.getAttributeNode('name').value)
// <input type="text" id="int" value="inputボックス" name="uname">
// 5.属性ノードを削除
console.log(int.removeAttribute('name'))
// <input type="text" id="int" value="inputボックス">
// 6.属性が存在するかどうかを判断
console.log(int.hasAttributes())
// true
// 7.指定された属性が存在するかどうかを判断
console.log(int.hasAttribute('value'))
// true
</script>
注意:
hasAttribute
とhasAttributes
の違い
hasAttributes
は属性が存在するかどうかを判断し、
hasAttribute
は指定された属性が存在するかどうかを判断します。