ここまででなんとなく(感覚的なものが大半を占めるw)、ToDoアプリがそこそこ動くところまで進めてきてしまったが、いよいよDOMについてちゃんと理解しておいた方がよいことに気づくww(遅!)
もちろん、なんとなくと言いつつ、ちゃんと「こうしよう!」と思って作ったToDoアプリではあるが、DOMの操作はちょっとふわっとしているのだ。
今回は、ここにメスを入れようと思う。
DOMとは?
DOMは、Document Object Modelの略。
今回もWiki先生から引用。
DOMは、HTML文書やXML文書(あるいはより単純なマークアップされた文章など)をオブジェクトの木構造モデルで表現することで、ドキュメントをプログラムから操作・利用することを可能にする仕組み
今回の例でいくと、JavaScriptのDOMを操作するAPIを使って、HTMLを書き換えちゃいましょう!という感じかな。(適当w)
要素の取得
まずは要素の取得から行ってみよう!
CodeSandboxを使って、どういう風に書いたら、どんなことが起こるのか、まず手を動かしてみます。
その前に、前提となるHTMLを紹介。
HTML
<body> <h1 id="list_title">List Title</h1> <div id="contents"> <div class="table"> <ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul> </div> <div class="content"> <p>リストの色々な説明など1</p> </div> <div class="content"> <p>リストの色々な説明など2</p> </div> </div> <script src="src/index.js"></script> </body>
CSSなどは設定していないので、いたってシンプルなHTML
このHTMLに対して、DOM操作として、要素を取得をやっていきます。
idで要素を取得する
HTML
<h1 id="list_title">List Title</h1>
JavaScript
const title = document.getElementById('list_title'); console.log(title);
結果
親ノードを取得
HTML
<div class="table"> <ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul> </div>
JavaScript
const list = document.getElementById('list'); console.log(list); console.log(list.parentNode); console.log(list.parentNode.className);
結果
属性の取得と追加
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
const list = document.getElementById('list'); // 属性の取得 const listAttr = list.children[0].getAttribute('class'); console.log(listAttr); // name属性を追加(F12で確認) list.children[0].setAttribute('name', 'test');
結果
クラス名で要素を取得する+要素の数を取得
HTML
<div class="content"> <p>リストの色々な説明など1</p> </div> <div class="content"> <p>リストの色々な説明など2</p> </div>
JavaScript
const content = document.getElementsByClassName('content'); console.log(content); console.log(content.length);
結果
innerHTMLとtextContent
HTML
<div class="content"> <p>リストの色々な説明など1</p> </div> <div class="content"> <p>リストの色々な説明など2</p> </div>
JavaScript
const content1 = document.getElementsByClassName('content')[0]; console.log(content1); // innerHTMLはタグも含めて取得 console.log(content1.innerHTML); // textContentはテキストのみを取得 console.log(content1.textContent); console.log(content1.firstElementChild.innerHTML); console.log(content1.firstElementChild.textContent); console.log(content1.children[0].innerHTML); const content2 = document.getElementsByClassName('content')[1]; console.log(content2); const content3 = document.getElementsByClassName('content')[2]; console.log(content3);
結果
Collectionと配列
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
// HTMLCollection const listContent = document.getElementsByClassName('list_content'); console.log(listContent); // Collectionを配列に変換① console.log(Array.prototype.slice.call(listContent, 0)); // Collectionを配列に変換② console.log([...listContent]); // タグが入った要素から文字列だけを取り出す const listArray = [...listContent]; for (let i = 0; i < listArray.length; i++) { console.log(listArray[i].textContent); }
結果
NodeListと配列
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
// NodeList const listContentArray = document.querySelectorAll('li'); console.log(listContentArray); // NodeListを配列に変換① console.log(Array.prototype.slice.call(listContentArray, 0)); // NodeListを配列に変換② console.log([...listContentArray]);
結果
兄弟要素の取得
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
const listContent1 = document.getElementsByClassName('list_content')[0]; console.log(listContent1); // nextElementSiblingは、改行やホワイトスペースを除いて取得 // nextSiblingは、改行やホワイトスペースが含まれる console.log(listContent1.nextElementSibling); console.log(listContent1.textContent); console.log(listContent1.nextElementSibling.textContent);
結果
要素の追加と削除
今度は要素を追加したり削除したりしてみる。
子要素の追加と削除
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
// 起点はlist const list = document.getElementById('list'); // 直下の子要素を削除 list.removeChild(list.firstElementChild); // 2番目の子要素を削除 list.removeChild(list.children[1]); // li要素の作成 const addList0 = document.createElement('li'); const addList4 = document.createElement('li'); // 追加した要素のテキスト追加 addList0.textContent = 'リスト0'; addList4.textContent = 'リスト4'; // 追加した要素にclassを追加 addList0.setAttribute('class', 'list_content'); addList4.setAttribute('class', 'list_content'); // 追加した要素をlistの下に挿入 list.insertBefore(addList0, list.firstChild); list.appendChild(addList4, list.firstChild); // コンソールに出力 console.log(list); console.log(addList0); console.log(addList4);
結果
子要素をまるっと削除
HTML
<ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul>
JavaScript
// 起点はlist const list = document.getElementById('list'); list.innerHTML = ''; // list.textContent = ''; <- こっちもイケる // コンソールに出力 console.log(list);
結果
要素そのものを削除
HTML
<div class="table"> <ul id="list"> <li class="list_content">リスト1</li> <li class="list_content">リスト2</li> <li class="list_content">リスト3</li> </ul> </div>
JavaScript
const table = document.getElementsByClassName('table')[0]; const list = document.getElementById('list'); list.remove(); console.log(table); console.log(list);
結果
最初は、list を remove() したはずなのに、なんでコンソールに出力されてるんだろうって思ったけど、list には取得したDOMが格納されていて、HTMLからその要素が削除されるだけなので、変数 list そのものには、さっき格納したDOMの情報が残っているということらしい。