In 'n' Out

知識を取り込み、そして発信する

DOM操作による要素の構造取得・操作

DOMツリーからの構造取得

DOMは、要素同士が親子関係や並び順を持つDOMツリーという構造で管理されています。
これまで紹介してきたgetElementやquerySelectorは、DOM全体から条件に合う要素を探して取得する方法でした。
一方、ここで扱うのは、すでに取得した要素を起点にして、親・子・兄弟といったDOMツリーの構造をたどりながら要素を取得する方法です。
これらの方法は、要素を新しく探すというより、取得済みの要素を基準に位置関係から要素を扱うための補助的な取得方法として使われます。
フォームの制御やイベント処理など、今操作している要素の周辺を扱いたい場面でよく使われるのが特徴です。

親要素を取得・操作する

ある要素を起点にして、その要素がどの要素の中に配置されているかをたどることができます。
要素同士の親子関係を利用して、構造に沿った操作を行いたい場合に使われます。

構文

要素.parentNode;

parentNodeは、指定した要素の 親にあたる要素 を取得するためのプロパティです。
今操作している要素が、どの要素の中に含まれているかを知りたい場合に使われます。

コード例

<article>
  <div>
    <p id="target">基点となるテキスト</p>
  </div>
</article>
.parentDiv {
    color: #ff0000;
}
//domParent.js
const base = document.getElementById('target');
const parentBase = base.parentNode;
const article = parentBase.parentNode;

base.textContent = parentBase.tagName + ' が親要素です。';

article.classList.add('parentDiv');

動作例

基点となるテキスト

※このボタンは動作確認用です

実行ボタンを押すと確認できます。
まず、baseにtargetが付与されているidの要素を取得して代入します。
次に、parentBaseにbaseの親要素であるdivを取得して代入します。
さらに、articleにparentBaseであるdivの親要素を取得して代入します。
引き続き、baseの直接の親要素タグ名に書き換えるようにします。
最後に、articleのクラスにparentDivを追加して、スタイルが適用されたため赤くなります。
このようにparentNodeで基点となる要素から親要素を取得でき、その親要素を変数や定数に代入すれば、その親要素を取得・操作できるようになります。

子要素をまとめて取得・操作する

ある要素を起点にして、その要素の中に含まれている子要素をまとめて扱うことができます。
要素同士の親子関係を利用して、複数の要素に対して同じ操作を行いたい場合に使われます。

構文

要素.children;

childrenは、指定した要素の子にあたる要素をまとめて取得するためのプロパティです。
今操作している要素の中に、どのような要素が含まれているかを知りたい場合に使われます。
なお、要素ノードのみを取得するため、改行や空白などのテキストは含まれません。

コード例

<article id="childrenEle">
    <h4>小見出し</h4>
    <p>説明文</p>
    <div>
        <span>補足説明文</span>
    </div>
</article>
//domChildren.js
const parent = document.getElementById('childrenEle');
const childEle = parent.children;
let grandchild = 0;

alert('子要素は' + childEle.length + 'つあります');

for (let i = 0; i < childEle.length; i++) {
    if (childEle[i].children.length > 0) {
        grandchild++;
    }
}
alert('孫要素は' + grandchild + 'つあります');

動作例

小見出し

説明文

補足説明文

※このボタンは動作確認用です

実行ボタンを押すと確認できます。
まず最初に、getElementByIdでchildrenEleのidが付与されている要素を取得し、parentに代入します。
次に、parentに対する子要素を取得します。
子要素の中にさらに子要素(孫要素)が存在するかを確認するために、grandchildを変数宣言しておきます。
すると子要素のarticleの子要素の数がalertに表示します。
続けてarticleの子要素の中に子要素、articleから孫要素があるかif文で、childEleの子要素が0より大きいかで判断し、あればgrandchildの数を増やします。
それをfor文で子要素の個数分処理をします。
最後に孫要素の数をalertで表示します。
このように子要素だけでなく、段階的にではありますが孫要素の取得も可能になります。

最初と最後の子要素を取得・操作する

ある要素を起点にして、その要素の中に含まれている 最初または最後の子要素 を取得して扱うことができます。
要素同士の親子関係を利用して、特定の位置にある要素だけを操作したい場合に使われます。

構文

//最初の子
要素.firstElementChild;
//最後の子
要素.lastElementChild;

firstElementChild・lastElementChildは、指定した要素の最初または最後の子にあたる要素を取得するためのプロパティです。
今操作している要素の中で、先頭や末尾に配置されている要素を扱いたい場合に使われます。

コード例

<article id="childEle">
    <h4>小見出し</h4>
    <p>説明文</p>
    <div>
        <span>補足説明文</span>
    </div>
</article>
//domChild.js
const parent = document.getElementById('childEle');
const firstChildEle = parent.firstElementChild;
const lastChildEle = parent.lastElementChild;

alert('最初の子要素は' + firstChildEle.tagName + 'です');
alert('最後の子要素は' + lastChildEle.tagName + 'です');

動作例

小見出し

説明文

補足説明文

※このボタンは動作確認用です

実行ボタンを押すと確認できます。
まず最初に、getElementByIdでchildrenEleのidが付与されている要素を取得し、parentに代入します。
次に、parentに対する最初の子要素を取得します。
続けてparentに対する最後の子要素を取得します。
最後に子要素のタグ名をalertで表示します。
なお、Visual Studio Code(VS Code)などのコード補完ツールを使う際に、firstChildやlastChildが候補として出てくることがありますが、全く用途が異なるので注意してください。

前後の兄弟要素を取得する

ある要素を起点にして、その要素の前後に配置されている兄弟要素を取得して扱うことができます。
要素同士の並び順を利用して、特定の位置にある要素だけを操作したい場合に使われます。

構文

//直後の要素
要素.nextElementSibling;
//直前の要素
要素.previousElementSibling;

nextElementSibling・previousElementSiblingは、指定した要素の前後にあたる兄弟要素を取得するためのプロパティです。
今操作している要素の直前や直後に配置されている要素を扱いたい場合に使われます。
要素が存在しない場合はnullが返ります。

コード例

<ul>
    <li>1番目の要素</li>
    <li>2番目の要素</li>
    <li class="active">3番目の要素</li>
    <li>4番目の要素</li>
    <li>5番目の要素</li>
</ul>
//domBrother.js
const base = document.querySelector('.active');
const nextEle = base.nextElementSibling;
const previousEle = base.previousElementSibling;

alert('次の要素' + nextEle.textContent + 'です');
alert('前の要素は' + previousEle.textContent + 'です');

動作例

  • 1番目の要素
  • 2番目の要素
  • 3番目の要素
  • 4番目の要素
  • 5番目の要素

※このボタンは動作確認用です

実行ボタンを押すと確認できます。
まず最初に、querySelectorでactiveクラスの付いた要素を取得します。
次に、nextElementSiblingでbaseの次の要素を取得します。
さらにpreviousElementSiblingでbaseの前の要素を取得します。
最後にbaseの前後のテキストをalertで表示します。
なお、Visual Studio Code(VS Code)などのコード補完ツールを使う際に、nextSiblingやpreviousSiblingが候補として出てくることがありますが、全く用途が異なるので注意してください。

取得方法の違い

getElementByIdやquerySelectorは、HTML全体の中から条件に一致する要素を探して取得するための方法です。
このIDの要素を取得したい、このクラスを持つ要素を取得したいといったように、取得したい要素を直接指定して使います。
一方、parentNodeやchildren、firstElementChild、nextElementSiblingなどは、すでに取得している要素を起点にして、その周囲の構造をたどりながら要素を取得するためのプロパティです。
HTMLの親子関係や並び順といった構造を利用して、関連する要素を取得・操作したい場合に使われます。
つまり、getElementやquerySelectorは要素を探して取得する方法であり、構造取得系のプロパティは取得済みの要素から関係する要素をたどる方法です。
どちらもDOMを操作するための手段ですが、使う場面と考え方が異なります。