吉本集の個人ブログ
Web制作の技術について書いています。たまに日記も書きます。

【JS入門】DOMについて Vol.5(ノードの生成・追加・複製・削除)

2018年2月6日 / category : javascript

今回の記事では、ノードの生成・追加・複製・削除について解説していきます。

ノードを生成する

ノードを生成するには、Documentインターフェースで定義されているメソッドcreateElementを使用します。

Document.createElement(tagName):指定したタグ要素を生成する。
引数 tagName : タグ名(string)
戻り値(return): Element
構文

let element = Document.createElement('p');

sample.js
let p = document.createElement('p');
console.log( p ); // <p><p>
console.log( typeof p ); // object
console.log( p.__proto__ ); // HTMLParagraphElement {...}

上のコードで、HTMLParagraphElementインターフェースのインスタンス(DOMオブジェクト)が生成されていることが確認できました。
ただし、生成されただけではHTML上に反映されませんので、この生成されたインスタンスをNodeインターフェースで定義されているメソッドappendChildを使用して反映(追加)します。

ノードを追加する

Node.appendChild(element):指定したElementオブジェクト(ノード)を対象ノードの末尾に追加する。
引数 element : 追加するElement(HTMLElement)
戻り値(return): 追加されたElement(HTMLElement)
構文

let element = Node.appendChild(element);

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<div id="content">
<h1>見出し</h1>
</div>
<script src="./js/sample.js"></script>
</body>
</html>
sample.js
let content = document.getElementById('content');
let p = document.createElement('p');
content.appendChild(p);
実装結果
<div id="content">
<h1>見出し</h1>
<p></p>
</div>

上のコードで、id属性にcontentを持つdiv要素の末尾に追加されました。ただし、追加したp要素にはテキストノードがないため空の状態です。プロパティtextContentを使って代入してみます。

sample.js
let content = document.getElementById('content');
let p = document.createElement('p');
p.textContent = 'お腹減った。';
content.appendChild(p);

console.log( p.textContent ); // お腹減った。
console.log( typeof p.textContent ); // string

console.log( p.firstChild ); // お腹減った。
console.log( typeof p.firstChild ); // object
console.log( p.firstChild.__proto__ ); // Text {...}
実装結果
<div id="content">
<h1>見出し</h1>
<p>お腹減った。</p>
</div>

これでブラウザ上に「お腹減った。」のテキストが反映されました。プロパティtextContentに代入したデータはテキストデータですが、p要素のプロパティfirstChildでテキストノードが生成されたのが確認できます。続いて属性を設定してみます。

sample.js
let content = document.getElementById('content');
let p = document.createElement('p');
p.textContent = 'お腹減った。';
p.style = 'color: #f00;';
p.className = 'txt';
content.appendChild(p);
実装結果
<div id="content">
<h1>見出し</h1>
<p class="txt" style="color: #f00;">お腹減った。</p>
</div>

ブラウザ上に追加された「お腹減った。」のテキストのフォントカラーが赤色になり、class属性にtxtが設定されました。

特定の子ノードの前に追加する

先ほどのメソッドappendChildは、対象ノードの末尾に追加されるメソッドでした。対象ノードのある特定の子ノードの前に追加する場合は、メソッドinsertBeforeを使用します。

Node.insertBefore(element, target):指定したElementオブジェクト(ノード)を子ノードであるtarget(ノード)の前に追加する。
引数 element : 追加するElement(HTMLElement)
引数 target : 前に追加するターゲットとなる子ノード(HTMLElement)
戻り値(return): 追加されたElement(HTMLElement)
構文

let element = Node.insertBefore(element, target);

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<div id="content">
<h1 id="heading">見出し</h1>
<p id="lead">リード文</p>
</div>
<script src="./js/sample.js"></script>
</body>
</html>
sample.js
let content = document.getElementById('content');
let lead = document.getElementById('lead');
let p = document.createElement('p');
p.textContent = 'お腹減った。';
p.style = 'color: #f00;';
p.className = 'txt';
let element = content.insertBefore(p, lead);
実装結果
<div id="content">
<h1 id="heading">見出し</h1>
<p class="txt" style="color: #f00;">お腹減った。</p>
<p id="lead">リード文</p>
</div>

新しく生成したp要素(ノード)がid属性にleadを持つp要素(ノード)の前に追加されました。

子ノードの最初(先頭)に追加する

子ノードの先頭に追加するメソッドは定義されていませんが、先ほどのメソッドinsertBeforeを使用して実装できます。

sample.js
let content = document.getElementById('content');
let p = document.createElement('p');
p.textContent = 'お腹減った。';
p.style = 'color: #f00;';
p.className = 'txt';
let element = content.insertBefore(p, content.firstChild);
実装結果
<div id="content">
<p class="txt" style="color: #f00;">お腹減った。</p>
<h1 id="heading">見出し</h1>
<p id="lead">リード文</p>
</div>

対象ノードの最初のノードの前に追加とすれば、子ノードの先頭(最初)に追加することになります。

ノードを複製する

ノードを複製するメソッドcloneNodeが定義されています。

Node.cloneNode(deep):対象ノードの値と属性を複製し新しいノードを生成します。
引数 deep(Boolean) : 対象ノードの子孫ノードも複製する場合はtrue, 対象ノードのみの場合はfalse
戻り値(return): 複製された新しいノード(HTMLElement)
構文

let element = Node.cloneNode(true);

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<div>
<ul id="list"></ul>
</div>
<script src="./js/sample.js"></script>
</body>
</html>
sample.js
const list = document.getElementById('list');
const listItem = document.createElement('li');
listItem.textContent = 'リストアイテム';
listItem.className = 'item';
const len = 3;
let clone;
for( let i=0; i<len; i++ ){
	clone = listItem.cloneNode(true);
	clone.textContent += (i+1) + '番目';
	list.appendChild(clone);
};
実装結果
<ul id="list">
<li class="item">リストアイテム1番目</li>
<li class="item">リストアイテム2番目</li>
<li class="item">リストアイテム3番目</li>
</ul>

for文内で生成したli要素を複製し、ul要素に追加しています。複製する際に属性と値も一緒に複製されていることがわかります。注意する点として、テキストもテキストノードとして扱われるためメソッドcloneNodeの引数にはtrueを設定する必要があります。ただし、このコードはあまり推奨できないコードです。理由については、後ほど解説します。

ノードを置き換える

ノードを置き換えるメソッドreplaceChildが定義されています。

Node.replaceChild(node, targetNode):対象ノードの子ノードを別のノードに置き換えます。
引数 node(HTMLElement) : 置き換えるノード
引数 targetNode(HTMLElement) : 置き換わる対象ノードの子ノード
戻り値(return): 置き換わる対象ノードの子ノード(HTMLElement)
構文

let element = Node.replaceChild(node, targetNode);

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<div id="content">
<p id="target">置き換えられる要素</p>
</div>
<script src="./js/sample.js"></script>
</body>
</html>
sample.js
const content = document.getElementById('content');
const target = document.getElementById('target');
const p = document.createElement('p');
p.textContent = '新しく生成された要素';
const oldNode = content.replaceChild( p, target );
console.log( oldNode ); // <p id="target">置き換えられる要素</p>
console.log( oldNode === target ); // true
実装結果
<div id="content">
<p>新しく生成された要素</p>
</div>

id属性にtargetを持つp要素が、生成されたp要素に置き換わりました。メソッドreplaceChildで返ってくるノードは、置き換わる要素と同じノードが返ってくるので、oldNodeとtargetを比較するとtrueが返ってきます。

ノードを削除する

ノードを削除するメソッドremoveChildが定義されています。

Node.removeChild(target):対象ノードの子ノードを削除(取り除く)します。
引数 target(HTMLElement) : 削除(取り除く)するノード
戻り値(return): 削除(取り除く)されたノード(HTMLElement)
構文

let element = Node.removeChild(target);

index.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>タイトル</title>
</head>
<body>
<div id="content">
<p id="target">削除された要素</p>
</div>
<script src="./js/sample.js"></script>
</body>
</html>
sample.js
const content = document.getElementById('content');
const target = document.getElementById('target');
const removeNode = content.removeChild( target );;
console.log( removeNode ); // <p id="target">削除された要素</p>
console.log( removeNode === target ); // true
実装結果
<div id="content">

</div>

以上が、ノードに関するメソッドの解説になります。