subtitle

RaiseTechの各種コースをはじめとしたイロイロな学習の記録

DOM操作を学ぶ

ここまででなんとなく(感覚的なものが大半を占める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の情報が残っているということらしい。