JavaScriptのDOMを操作して要素を追加・削除する方法をまとめました。
また、input要素、セレクトボックス、ラジオボタン、チェックボックスなどへの挿入方法も紹介しています。
先に結論だけまとめます。要素の削除はelement.remove()、追加はparent.append()(末尾)かparent.prepend()(先頭)、位置を指定した挿入はinsertAdjacentElement()またはinsertAdjacentHTML()を使います。appendChild()やremoveChild()も動きますが、現在のブラウザでは上の短い書き方で足ります。
const list = document.querySelector('ul');
const item = document.createElement('li');
item.textContent = '新しい項目';
list.append(item); // 末尾に追加
list.prepend(item); // 先頭に移動(同じ要素は1か所にしか存在しない)
list.insertAdjacentElement('afterbegin', item); // 位置を指定して挿入
item.remove(); // 削除
DOM要素の生成方法
createElement()
const message = document.createElement('div');
DOM要素を生成します。
DOMはページ上のどこにもないです。ページ上に表示したいときは、手動で挿入する必要があります。
このmessageはDOM要素であり、documentで使っていたメソッドなどが使えます。
生成したDOM要素のテキストを設定する
textContent() プロパティ
message.textContent = 'クッキーを分析のために使います。'; //テキストを設定します。
textContentはNodeのプロパティです。
scriptタグとstyleタグを含む、すべての要素のテキストを取得します。
innerText() プロパティ
message.innerText = 'クッキーを分析のために使います。';
innerTextはエスケープ文字がその通りに機能します(例:改行、タブなど)。
innerTextはCSSを考慮してスタイルを反映し、「非表示」の要素のテキストは返しません。
innerHTML() プロパティ
message.innerHTML = 'クッキーを分析のために使います。';
message.innerHTML = '重要';
//「重要」は太字で表示されます。
innerHTMLはHTMLタグがあるとタグとして機能させられます。
textContentやinnerTextではできないことで、HTMLタグを書いても「<strong>重要</strong>」と文字のまま表示されます。
ただし、ユーザーが入力した文字列をinnerHTMLに渡すとスクリプトが混入する(XSS)恐れがあるので、外部由来の文字列はtextContentで入れてください。
他に、下で紹介するinsertAdjacentHTML()で代替できる場合が多いです。
また、CSSのstyle属性やclass属性の操作は、次の記事を参考にしてみてください。id属性やdata属性など属性全般の操作はJavaScriptでHTML属性を操作する方法にまとめています。
JavaScriptでclass属性とstyle属性を操作する方法まとめ
DOM要素の挿入方法
header.prepend(message);// ParentNodeの最初に追加
header.append(message);// ParentNodeの最後に追加
header.append(message.cloneNode(true));//コピー作成
header.before(message);//要素の前に挿入
header.after(message);// 要素の後に挿入
header.insertAdjacentHTML('beforebegin', html);//elementの開始タグの前に挿入
header.insertAdjacentHTML('afterbegin', html);//elementの開始タグの後に挿入
header.insertAdjacentHTML('beforeend', html);//elementの終了タグの前に挿入
header.insertAdjacentHTML('afterend', html);//elementの終了タグの後に挿入
prepend()メソッド
header.prepend(message);// ParentNodeの最初に追加
prepend()メソッドは、NodeオブジェクトまたはDOMStringオブジェクトのセットを ParentNodeの最初の子の前に挿入します。DOMStringオブジェクトは、同等のTextノードとして挿入されます。
append()メソッド
header.append(message);// ParentNodeの最後に追加
append()メソッドは、prepend()の逆で、ParentNodeの最後に追加します。なお、どちらも設定した場合は、あとに書かれたもののみ適用されます。DOM要素はひとつしか存在しないためです。動作としては、prepend()で挿入されて、その後append()で移動しています。
では、同じ要素を複数箇所に挿入したい場合、どうすればいいでしょうか?
その場合がコピーを作成します。
cloneNode()メソッド
header.append(message.cloneNode(true));//コピー作成
cloneNode()メソッドはNodeをコピーできます。引数にtrueを渡すと子要素まで含めて複製し、falseならその要素だけを複製します。
before()メソッド
header.before(message);//要素の前に挿入
before()メソッドは指定した要素の前にNodeまたはDOMStringオブジェクトを挿入できます。
after()メソッド
header.after(message);// 要素の後に挿入
after()メソッドは指定した要素の後にNodeまたはDOMStringオブジェクトを挿入できます。
insertAdjacentHTML()メソッド
containerMovements.insertAdjacentHTML('beforebegin', html);
//elementの開始タグの前に挿入
containerMovements.insertAdjacentHTML('afterbegin', html);
//elementの開始タグの後に挿入
containerMovements.insertAdjacentHTML('beforeend', html);
//elementの終了タグの前に挿入
containerMovements.insertAdjacentHTML('afterend', html);
//elementの終了タグの後に挿入
insertAdjacentHTML()は第一引数で指定した場所に、第二引数で指定したものを入れられます。
insertAdjacentElement()メソッド
const note = document.createElement('p');
note.textContent = '注意書き';
header.insertAdjacentElement('beforebegin', note); // headerの直前
header.insertAdjacentElement('afterend', note); // headerの直後
insertAdjacentElement()は、insertAdjacentHTML()と同じ4つの位置指定で、文字列ではなく要素を挿入します。createElement()で作った要素を「兄弟として」置きたいときに便利です。テキストだけを差し込むinsertAdjacentText()もあります。
DOMツリーに要素を追加する
ulタグの中のliタグの中にテキストを追加したいとしましょう。
その場合、やることは次の3ステップとなります。
- li要素を作る
- テキストを作成する
- DOMツリーに追加する
2番で要素自体ができあがります。
ただそれだけではDOMツリーに入っていないので、DOMツリーに追加するステップが最後に必要になります。
親Nodeの子要素の末尾に追加する手法を使います。
要素を作る
要素を作るのは、document.createElementを使います。
(‘li’)とすればliの空要素を作れます。
テキストを作成する
それを定数に入れておきます。ここでは定数をitem2とします。
そして、textを足す場合は、item2のtextContent = ‘item2’としておけばOKです。
DOMツリーに追加する
DOMツリーに追加するには、まずは親要素を取得します。
今回はulなので、ulという文字列をdocument.querySelectorに渡すために、次のように定数ulに格納します。
const ul = document.querySelector('ul');
const ulのulは定数、querySelector(‘ul’)のulはquerySelectorに渡すための要素名の文字列と区別できるのであれば、定数にulとしてもOKです。
あとはulの末尾に子要素として追加すればOKです。
その際、appendChild()というメソッドを使います。
ul.appendChild(item2);
要素の複製、挿入をする
上のliを矢印部分に複製して挿入したいとします。
その場合次のステップが必要です。
- li要素を複製する
- DOMツリーに追加する
この場合、親要素のある子要素を、最後の子要素の前に追加するという手法を使います。
まず、選択するには、今まで通りです。
const item0 = document.querySelectorAll('li')[0];
querySelectorAll()で取得したNodeListに、複製したいインデックス番号を指定します。
そして、複製したい場合は、cloneNodeを使います。
const copy = item0.cloneNode(true);
cloneNode(false)とすると、空のli要素を複製します。
今回は中身もコピーしたいので、trueにします。
次に、親要素を取得します。
const ul = document.querySelector('ul');
そして、item2の前に入れたいので、item2も取得します。
const item2 = document.querySelectorAll('li')[2];
そして、insertBeforeというメソッドで、copyをitem2の前に挿入する命令をつくります。
ul.insertBefore(copy, item2);
HTML
<ul>
<li>aaa</li>
<li>bbb</li>
<li>ccc</li>
</ul>
<button>add</button>
JavaScript
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const item0 = document.querySelectorAll('li')[0];
const copy = item0.cloneNode(true);
const ul = document.querySelector('ul');
const item2 = document.querySelectorAll('li')[2];
ul.insertBefore(copy, item2);
});
}
要素を削除する
DOMから要素を削除するやり方をみてみましょう。
「javascript remove」で探している方への答えはこれだけです。削除したい要素を取得してremove()を呼ぶと、その要素は子要素ごとDOMツリーから外れます。戻り値はなく、取得しておいた変数には要素が残るので、あとでappend()すれば同じ要素を再び表示できます。
今回はitem1を削除してみます。
まずはitem1を取得します。
そして、removeメソッドを実行します。
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const item1 = document.querySelectorAll('li')[1];
item1.remove();
});
}
remove()メソッドの注意点
remove()メソッドは現在の主要ブラウザすべてで使えますが、Internet Explorerでは使えませんでした。古いコードやライブラリでは、次の書き方を今でも見かけます。
親Node.removeChild(削除するNode)という方法です。
'use strict';
{
// 昔のやり方
const message = document.createElement('div');
message.parentElement.removeChild(message);
}
削除したいNodeを選び、その親(parentElement)に対してremoveChild()を呼び、()の中に削除したいNodeを指定します。
複数の要素をまとめて削除したいときは、querySelectorAll()で取得したNodeListをforEachで回して、それぞれremove()します。
document.querySelectorAll('.is-done').forEach((el) => el.remove());
削除した要素に登録していたイベントは要素と一緒に消えます。クリックなどのイベント登録はaddEventListenerの基本とさまざまな使い方で解説しています。
input要素を操作する
フォームに入力してボタンを押したら、下に追加されていく仕組みを作ってみましょう。
要素はliで追加していくとしましょう。
手順は次の通りです。
- li要素をつくる
- inputタグの内容を取得して定数に入れる
- li要素にそれをいれる
- ulに追加する
まずはボタンを押したときに処理を実行する命令をつくります。
document.querySelector('button').addEventListener('click', () => {
});
li要素をつくるには、次の通りです。
const li = document.createElement('li');
そして、inputで入力されたものをテキストにいれたいので、まずはinputを取得してtextという名前の定数に保管しましょう。
const text = document.querySelector('input');
そして、li要素にinputに入力された内容をセットします。
入力された内容は、valueで取得できます。
li.textContent = text.value;
そして、ulに対してappendChildで定数liを指定して、li要素を追加してあげれば完成です。
document.querySelector('ul').appendChild(li);
HTML
<p>好きな言葉を入力してください。</p>
<input type="text">
<button>click</button>
<p>この下に追加される</p>
<ul>
</ul>
JavaScript
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const li = document.createElement('li');
const text = document.querySelector('input');
li.textContent = text.value;
document.querySelector('ul').appendChild(li);
});
}
セレクトボックスを操作する
次は、セレクトボックスで好きな動物を選んでボタンを押したら追加される仕組みをつくってみましょう。
inputと似たような流れになります。
手順は次の通りです。
- li要素をつくる
- selectタグの内容を取得して定数に入れる
- li要素にそれをいれる
- ulに追加する
selectの場合、値と選択された値が何番目かといった情報も取得できるので両方取得してみましょう。
selectedIndexでインデックス番号を取得できます。
HTML
<select>
<option>犬</option>
<option>猫</option>
<option>猿</option>
<option>鹿</option>
<option>ゾウ</option>
</select>
<button>click</button>
JavaScript
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const li = document.createElement('li');
const animal = document.querySelector('select');
li.textContent = `${animal.value} - インデックス番号${animal.selectedIndex}番です`;
document.querySelector('ul').appendChild(li);
});
}
valueの値には、タグの中身が使われる(犬)のですが、変更したい場合は、htmlにvalue属性をセットするとvalue属性の値が表示されます。
ラジオボタンを操作する
ラジオボタンは、セレクトボックスと違って最初にひと手間必要になります。
手順は次の通りです。
- すべての選択肢を取得して定数に入れる
- 選んだ値を保持するために変数を宣言する
- すべての選択肢に対してループ処理をする
- checkedプロパティがついていればvalueを変数にセットするという条件式をつくる
そして後は同じような流れになります。
- li要素をつくる
- 変数の内容を取得してliの定数に入れる
- li要素にそれをいれる
- ulに追加する
まずはボタンを押したときに処理を実行する命令をつくります。
document.querySelector('button').addEventListener('click', () => {
});
すべての選択肢を取得して定数に入れるには次の通りです。
const animals = document.querySelectorAll('input');
そして、選択した値を保持しておきたいので、変数を宣言しておきます。
let selectedAnimal;
その上で、forEachを使って、animalsに対してループ処理をします。
animals.forEach(animal => {});
要素がチェックされていたら、その要素を代入します。
チェックされているかは、checkedプロパティで調べられます。
checkedがあったら、animalのvalueプロパティをselectedAnimalに代入するという条件式をつくります。
if (animal.checked === true) {
selectedAnimal = animal.value;
}
そしたら、後は同じような流れになります。
li要素をつくります。
const li = document.createElement('li');
定数liのテキストに選択された値が保持されている変数を代入します。
li.textContent = selectedAnimal;
定数liをulに追加します。
document.querySelector('ul').appendChild(li);
HTML
<input type="radio" name="animal" value="dog"> 犬
<input type="radio" name="animal" value="cat"> 猫
<input type="radio" name="animal" value="monkey"> 猿
<button>click</button>
<p>下に追加されます。</p>
<ul>
</ul>
JavaScript
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const animals = document.querySelectorAll('input');
let selectedAnimal;
animals.forEach(animal => {
if (animal.checked === true) {
selectedAnimal = animal.value;
}
});
const li = document.createElement('li');
li.textContent = selectedAnimal;
document.querySelector('ul').appendChild(li);
});
}
チェックボックスを操作する
チェックボックスとラジオボックスとの違いは、複数選択できる点です。
手順は次の通りです。
- すべての選択肢を取得して定数に入れる
- 選んだ値を保持するために変数を宣言する(複数選択可なので配列で宣言)
- すべての選択肢に対してループ処理をする
- checkedプロパティがついていればvalueを変数にセットするという条件式をつくる
そして後は同じような流れになります。
- li要素をつくる
- 変数の内容を取得してliの定数に入れる
- li要素にそれをいれる
- ulに追加する
まずはボタンを押したときに処理を実行する命令をつくります。
document.querySelector('button').addEventListener('click', () => {
});
animalsという定数に、inputを全部選択して入れます。
const animals = document.querySelectorAll('input');
複数選択が可能なので、配列で保持します。
配列の内容は変化しますが、再代入はしないので、constで宣言します。
const selectedAnimals = [];
forEachで要素をそれぞれ調べます。
animals.forEach( animal => {});
選ばれたcheckboxは、ラジオボタンとほぼ同じ流れになります。
checkedプロパティがtrueだったら、trueという条件式をつくります。
if (animal.checked === true) {});
そして、selectedAnimalsに追加したいので、pushメソッドを使います。
selectedAnimals.push(animal.value);
後は、同じような流れになります。
配列なので、joinでカンマ区切りにしてあげるといいでしょう。
ただ、配列は文字列に変換されるときカンマ区切りになるので、join()はなくてもOKです。
const li = document.createElement('li');
li.textContent = selectedAnimals.join(', ');
document.querySelector('ul').appendChild(li);
HTML
<input type="checkbox" name="animal" value="dog"> 犬
<input type="checkbox" name="animal" value="cat"> 猫
<input type="checkbox" name="animal" value="monkey"> 猿
<button>click</button>
<p>下に追加されます。</p>
<ul>
</ul>
JavaScript
'use strict';
{
document.querySelector('button').addEventListener('click', () => {
const animals = document.querySelectorAll('input');
const selectedAnimals = [];
animals.forEach(animal => {
if(animal.checked === true) {
selectedAnimals.push(animal.value);
}
});
const li = document.createElement('li');
li.textContent = selectedAnimals.join(', ');
document.querySelector('ul').appendChild(li);
});
}
ここまでの操作がなぜ画面に反映されるのか、HTMLとDOMツリーの関係から知りたい方はDOMとは?HTMLがJavaScriptで操作できる仕組みを参考にしてください。追加したli要素のクリックをulでまとめて受け取りたい場合は、イベント伝播(バブリング)とdelegationの考え方が役立ちます。