ラボ > Javascript関連:DOM関連

javascriptで要素を追加したい(createElement、createTextNode、createElementNSなど)

タグじゃなくてテキストを追加したいときにcreateElementだと出来ない…ついでに複製方法も。

作成日:2024-03-29, 更新日:2024-03-29

HTMLを追加: createElement

let elm = document.createElement('div');

テキストを追加: createTextNode

let elm = document.createTextNode('丸ごとシマウマ');

名前空間を持つ要素(SVGやXMLなど): createElementNS

let elm = document.createElementNS('http://www.w3.org/2000/svg', 'svg');

コメントノード(<!-- xxx -->): createComment

let elm = document.createComment('丸ごとシマウマ');

要素の複製: cloneNode

let orig = document.querySelector('.xxx');
let shallow_elm = orig.cloneNode(false);
let deep_elm = orig.cloneNode(true);

cloneNode()の引数

子要素ごと複製、親要素のみ複製と振り分けが可能

複製元にする要素のサンプル

let elm_label_choiceFile = document.createTextNode('写真・動画を選択');

let elm_ipt_choiceFile = document.createElement('input');
elm_ipt_choiceFile.setAttribute('type', 'file');
elm_ipt_choiceFile.setAttribute('name', 'choiceFile');
elm_ipt_choiceFile.setAttribute('accept', 'image/*, video/*');
elm_ipt_choiceFile.oninput = function(){
  alert('xxx');
}

let elm_formSample = document.createElement('div');
elm_formSample.appendChild(elm_label_choiceFile);
elm_formSample.appendChild(elm_ipt_choiceFile);

親要素だけ複製(shallow clone): cloneNode(false)

この場合だと「div」のみ複製

let shallow_elm = orig.cloneNode(false);

子要素ごと複製(deep clone): cloneNode(true)

この場合だと「div」の子にある「写真・動画を選択」や「inputタグ」、inputタグのイベントも複製

let deep_elm = orig.cloneNode(true);

cloneNode()で複製した要素の修正

let elm_label_choiceFile = document.createTextNode('写真・動画を選択');

let elm_ipt_choiceFile = document.createElement('input');
elm_ipt_choiceFile.setAttribute('type', 'file');
elm_ipt_choiceFile.setAttribute('name', 'choiceFile');
elm_ipt_choiceFile.setAttribute('accept', 'image/*, video/*');
elm_ipt_choiceFile.oninput = function(){
  alert('xxx');
}

let elm_formSample = document.createElement('div');
elm_formSample.appendChild(elm_label_choiceFile);
elm_formSample.appendChild(elm_ipt_choiceFile);
document.body.appendChild(elm_formSample);

let elm_form_TakePic = elm_form_choiceFile.cloneNode(true);
elm_form_TakePic.childNodes[0].textContent = '写真を撮る'; // テキストノードは…取得できないので子ノードから取得
// let elm_ipt_TakePic = elm_form_TakePic.childNodes[1]; // こっちでもいける。メンテナンス(元のほうで順番を変更したりするかも…)を考えると避けたい
let elm_ipt_TakePic = elm_form_TakePic.querySelector('input');
elm_ipt_TakePic.setAttribute('capture', 'camera');
elm_ipt_TakePic.setAttribute('accept', 'image/*');
document.body.appendChild(elm_form_TakePic); // elm_ipt_TakePicじゃなく、元になるelm_form_TakePicを追加

テンポラリデータの作成: createDocumentFragment

let elm_temporary = document.createDocumentFragment();

使い道は…

  • ループなどで何個も要素を追加したいとき - 一つの要素ずつ描画するのではなく、まとめて描画
  • 複雑なHTMLなどを追加したい - タイトルを描画後、本文を描画して、さらにボタンを描画じゃなく、まとめて描画
  • テンプレートにしたい - 使いまわすことが可能。cloneNode()を合わせれば色々と出来そう…

使い道: ループなどで何個も要素を追加したいとき

createDocumentFragmentを使うと描画が一回だけになる

createDocumentFragmentを使わない場合

「document.body.appendChild()」で毎回、描画が行われるのでパフォーマンスが落ちる

for (let i = 0; i < 10; i++) {
  let newElement = document.createElement('p');
  newElement.textContent = 'Paragraph ' + i;
  document.body.appendChild(newElement);
}

createDocumentFragmentを使う場合

「document.body.appendChild()」の描画が1回だけなのでパフォーマンスがあまり落ちない

let elm_temporary = document.createDocumentFragment();

for (let i = 0; i < 10; i++) {
  let newElement = document.createElement('p');
  newElement.textContent = 'Paragraph ' + i;
  elm_temporary.appendChild(newElement);
}

document.body.appendChild(elm_temporary);