0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Dot install】Document Object Model (DOM)基礎編まとめ

Posted at

目的

Dot installで詳解されているDocument Object Motel (DOM)の内容をまとめる。
//ProgateだとDOMは扱われなかった。

対象

  • DOM基礎を学びたい方
  • Dot installを一周し、復習をしたい方

詳解JavaScript DOM編

HTMLの基礎 ~DOMとは~

  1. HTMLを読み込む
  2. DOMと呼ばれるデータ構造が作成される
  3. その内容に応じてページが描画される
    1. Javascriptで操作するのは、htmlではなく、DOM。

Nodeとは

  • DOM内の1つ1つのデータをNodeと呼ぶ。
  • Documentから始まり、ツリー状に枝分かれ=Node Tree (DOM Tree)

Nodeの種類

  • HTMLの要素を表すNode:Element Node (要素Node)
    • eg. <head>, <title>
  • Text、改行、空白:Text Node
    • 改行、空白もNode。
      • ただしhtml要素の先頭と末尾の改行、空白はNodeにならない。

Node間の関係

  • 親子・兄弟といった単語を頻用する。
    • eg. headに対するhtml: Parent Node
    • eg.2 headに対するtitle: Chiled Node
    • eg.3 </head>後の改行、空白と<body>: Sibling Node

DOMの操作

  • DOMはdocumentオブジェクトで操作。

要素の取得

  • querySelector(狙う要素(Selector)): 文書内から特定のSelectorを取得する。

  • 要素を取得する際にcssクラスまたはid属性で指定する。

    • id属性を指定する際には要素名の前に#をつける。
    • 見つかった要素のうち、最初の1つしか取得しない。
  • querySelectorAll(狙う要素(Selector))[i]: 文書内の指定したSelectorすべてを対象とする。iには要素のindex(何番目か?)を指定する。

    • オブジェクトなので、.forEach()が使用可。
    • 他にも
      • getElementByTagName('h1'): 文書内の指定したTagすべてを取得
      • getElementByClassName('box'): 文書内の指定したclassすべてを取得
  • getElementById: id属性を取得する。

    • 要素名の前に#は不要。
  • .chileNode: 要素の child nodeをすべて取得する。

    • .children: child nodesのうちelement nodesのみ取得する。
    • .firstChild: 最初のchild noteを取得
    • .lastChild: 最後のchild noteを取得
    • .firstElementChild: 最初のchild note (element node)を取得
    • .lastElementChild: 最後のchild note (element node)を取得
  • .parentNode: 要素の parent nodeを取得する。

  • .previousSibling: 要素の前のsibling nodeを取得する。

    • .previousElementSibling: 要素の前のsibling node (element node) を取得する。
  • .nextSibling: 要素の後のsibling nodeを取得する。

    • .nextElementSibling: 要素の後のsibling node (element node) を取得する。

コードサンプル

  • querySelector(狙う要素)およびgetElementById
index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <title>Javascript DOM Practice</title>
  </head>
  <body>
    <h1 id="target">hogehoge</h1>
    <p>fugafuga</p>
    <p>fugafuga</p>
    <p>fugafuga</p>
    <script src="js/main.js"></script>
  </body>
</html>
main.js
{
  function update() {
    document.querySelector('#target').textContent = "Changed!";
  }

  setTimeout(update, 1000);
}

または

main.js
{
  function update() {
    document.getElementById('target').textContent = "Changed!";
  }

  setTimeout(update, 1000);
}
  • querySelectorAll(狙う要素)
main.js
{
  function update() {
    document.querySelectorAll('p').forEach((p, index) => {
      p.textContent = `${index}番目のpです!`;
    });
  }
  setTimeout(update, 1000);
}

イベント

  • .addEventListener(動作, 関数): 指定したnodeについて、ある動作が起きた際に関数で指定した処理をする。
main.js

// button要素をclickした際に、target idのテキストをChanged!に変更する。

document.querySelector("button").addEventListener("click", () => {
    document.getElementById("target").textContent = "Changed!";
}); 

要素の操作

  • h1タグのtitlecolor, background-color要素を操作する。
main.js
document.querySelector("button").addEventListener("click", () => {
  const targetNode = document.getElementById("target");

  targetNode.textContent = "Changed!";
  targetNode.title = "This is my title!";
  targetNode.style.color = "red";
  targetNode.style.backgroundColor = "skyblue";
});

補足

CSSではbackground-colorと指定していたが、javascriptではbackgroundColorのように、ーを消して2単語目を大文字にする。

※ただし、一般的に見た目の指定は上記のように直接行うのではなく、classを付与する形で行う。

クラスの操作

  • .className = "": classを""内に書き換え

注意!

もともとclassが指定されている要素の場合、classNameで付与したクラスに完全に書き換わる。

  • .classList.add(""): ""のclassを新規追加。
  • .classList.remove(""):""のclassを消去。
  • .classList.contains(""): ""のclassの有無を確認。結果はbooleanで返される。
main.js

document.querySelector("button").addEventListener("click", () => {
  const targetNode = document.getElementById("target");

  //"my-color"classが付与されていたら消去し、付与されていなかったら追加する。

  if (targetNode.classList.contains('my-color') === true) {
    targetNode.classList.remove("my-color"); 
  } else {
    targetNode.classList.add("my-color");
  }
  
});


  • 上記と同様の挙動は.classList.toggle()で記載可能。
main.js

document.querySelector("button").addEventListener("click", () => {
  const targetNode = document.getElementById("target");

  //"my-color"classが付与されていたら消去し、付与されていなかったら追加する。
  targetNode.classList.toggle("my-color");  
});

カスタムデータ属性の操作

  • .dataset.(カスタムデータ属性)
    htmnl, jsにデータが分散していると後から編集しづらい。そこで、htmlにまとめてデータ属性を付与することで後からの編集をしやすくする。
index.html
<body>
  <button>Run!</button>
  <h1 id="target" data-translation="HOGEHOGE">hogehoge</h1>
  <p>fugafuga</p>
  <p>fugafuga</p>
  <p>fugafuga</p>
  <script src="js/main.js">
  </script>
</body>
main.js
  document.querySelector("button").addEventListener("click", () => {
    const targetNode = document.getElementById("target");

    //h1タグのtextをtranslationで指定した内容に変更する。
    targetNode.textContent = targetNode.dataset.translation;
  });

要素の追加

  • createElement('追加したい要素'): 追加したい要素を生成。
    あとは、追加したい要素をquerySelector等で指定すればok.
  document.querySelector("button").addEventListener("click", () => {
    const item2 = document.createElement('li'); //li要素を生成
    item2.textContent = "fuga 2"; //li要素のtextを指定

    const ol = document.querySelector('ol'); 
    ol.appendChild(item2); //ol要素の下に追加

  });

要素の複製と追加

  • .cloneNode(boolean): 指定したノードの複製。()内trueでcontentまで複製。
  • .insertBefore(挿入したいnode, 挿入する場所(このnodeの前に挿入される)): 指定したnodeの前にnodeを追加する。
document.querySelector("button").addEventListener("click", () => {
    const item0 = document.querySelectorAll("li")[0];
    const copy = item0.cloneNode(true); //item0のnodeを複製してcopy nodeを生成。falseの場合はitem0のtextが複製されない

    const ol = document.querySelector('ol');

    const item2 = document.querySelectorAll('li')[2];
    ol.insertBefore(copy, item2); //item2の前にcopy nodeを追加。
});

要素の削除

  • .remove('削除したいnode'): 一部のブラウザで対応不可。
  • .removeChild('削除したいnodeの親node'): 汎用的に使える方法

{
  document.querySelector("button").addEventListener("click", () => {
    const item1 = document.querySelectorAll('li')[0];


    item1.remove(); //item1 nodeを削除。ただし一部のブラウザでは対応不可。よって書き方も覚えておく。
    document.querySelector('ol').removeChild(item1); 

  });
}


input要素, option要素, ラジオボタンの操作

input要素

  • inputに入力された内容 => node名.valueで取得可能。
    textContentnode名.valueで取得した値を代入する等すれば、inputで受け取った値を表示することが可能になる。
index.html
<!-- headは省略 -->

<body>
  <input type="text">
  <button>Add</button>

  <ul>
  </ul>

  <script src="js/main.js">
  </script>
</body>

main.js
{
  document.querySelector("button").addEventListener("click", () => {
    const li = document.createElement("li"); //li要素を追加。
    const text = document.querySelector("input");
    li.textContent = text.value; //inputフォームに記載された値(value)を取得してli nodeのtextとして代入。
    document.querySelector('ul').appendChild(li);

    text.value = "";
    text.focus();

  });
}

option要素

  • selectに対しても、valueで値を取得できる。
index.html
<body>
  <select>
    <option></option>
    <option></option>
    <option></option>
  </select>

  <button>Add</button>

  <ul>
  </ul>

  <script src="js/main.js">
  </script>
</body>

main.js
{
  document.querySelector("button").addEventListener("click", () => {
    const li = document.createElement("li");
    const color = document.querySelector("select"); //select内にぶらさがっているchild nodeがすべて取得される。
    li.textContent = `${color.value} - ${color.selectedIndex}`;

    document.querySelector('ul').appendChild(li);

    color.focus(); 
  });
}

ラジオボタン

  • ラジオボタンが複数ある場合、input要素をすべて取得する必要があるため、select要素とは異なる点に注意。
index.html
<body>
  <input type="radio" name="color" value="red"><input type="radio" name="color" value="yellow"><input type="radio" name="color" value="blue"><button>Add</button>

  <ul>
  </ul>

  <script src="js/main.js">
  </script>
</body>

{
  document.querySelector("button").addEventListener("click", () => {
    const colors = document.querySelectorAll("input"); //ここですべてのラジオボタンを取得。
    
    let selectedColor; //選択したボタン(色)を入れる変数を準備

    colors.forEach(color => {
      if (color.checked === true) {
        selectedColor = color.value; //ラジオボタン.checkedがtrueとなっている要素の値をselectedColor変数に代入
      }
    });

    const li = document.createElement("li");
    li.textContent = selectedColor;
    document.querySelector('ul').appendChild(li);
  });
}

チェックボックス

  • チェックボックスは複数選択可で、チェックした要素を配列で扱うことに注意。
index.html
<body>
  <input type="checkbox" value="red"><input type="checkbox" value="yellow"><input type="checkbox" value="blue"><button>Add</button>

  <ul>
  </ul>

  <script src="js/main.js">
  </script>
</body>
main.js
{
  document.querySelector("button").addEventListener("click", () => {
    const colors = document.querySelectorAll("input");
    const selectedColors = []; //チェックボックスの場合、複数選択可。要素を配列で保持しておく。配列の内容は変わるが、再代入はされないため、constで宣言する。

    colors.forEach(color => {
      if (color.checked === true) {
        selectedColors.push(color.value); //pushでtrueだったcolorのvalue追加
      }
    });

    const li = document.createElement("li");
    li.textContent = selectedColors.join(","); //, 区切りで値を代入
    document.querySelector("ul").appendChild(li);


  });
}
  • 配列への要素の追加: .push()
  • 配列を文字列として代入: .join('区切り文字')

様々なイベント

  • dblclick: ダブルクリックしたとき
  • mousemove: マウスを動かしたとき
  • keydown: キーを押したとき
    • ここで引数を渡すと、マウスの座標・押されたキー等取得できる。
    • ここで指定する引数をevent objectと呼び、慣習的にeで指定される。

'use strict';

{
  document.querySelector("button").addEventListener("dblclick", () => {
    console.log("Double click!");
  });

  document.addEventListener("mousemove", e => { //ここで引数を渡せば、ブラウザからイベントからの情報を渡してくれる
    //ここでの引数は、event objectと呼ばれ、慣習的にeが用いられる。
    console.log("Mouse moved!");
    console.log(e.clientX, e.clientY);
  });

  document.addEventListener("keydown", e => {
    console.log(e.key);
  });

}

textarea関係

  • focus: textareaにフォーカスされたとき
  • blur: textareaからフォーカスが外れたとき
  • input: textareaに文字が入力されたとき
  • change: textareaに入力された文字が確定されたとき

'use strict';

{
  const text = document.querySelector("textarea");

  text.addEventListener("focus", () => { //focusあたった際のイベント
    console.log("focus.");
  })

  text.addEventListener("blur", () => { //focus外れた際のイベント
    console.log("blur.");
  })

  text.addEventListener("input", () => { //文字が入力された際のイベント
    console.log("input.");
    console.log(text.value.length); //入力された文字カウント
  })

  text.addEventListener("change", () => { //入力された文字が確定した際のイベント
    console.log("change.");
  })


}

form

  • formについては、submitがイベントとなる。
    • formをもちいることのメリット:エンターキーでform内のテキストが送信される。
    • 通常はsubmitするとページがリロードされる。e.preventDefaultによって、リロードする通常動作をキャンセルできる。
    • フォームをエンターキーで送信するには、formタグの中にbuttonタグが必要だが、formタグ中に<input type=”text”>が1つだけだった場合はbuttonを省略してもエンターキーだけで送信できる。
'use strict';

{
  document.querySelector("form").addEventListener("submit", e => {
    e.preventDefault(); //リロードする通常動作をキャンセルする。
    console.log("Submit!");
  });
}

イベントの伝播

  • addEventListenerの引数でtargetとすれば、child nodeすべてがイベントの対象となる。
index.html
<body>
  <ul> <!-- e.currentTarget -->
    <li>To do</li>
    <li>To do</li> <!-- e.target -->
    <li>To do</li>
  </ul>

  <script src="js/main.js">
  </script>
</body>
main.js
{
  document.querySelector("ul").addEventListener("click", e => {
    if (e.target.nodeName === "LI") { //nodeNameは大文字
      e.target.classList.toggle("done");
    }
  });

}


以上。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?