どうも、イソップです。
DOMについての連載第4回目です。
今回も前回に引き続き、DOMを取得する方法について紹介します。
クラス名で取得する
クラス名での取得は、getElementsByClassName
メソッドを使用します。
ページ中にある、指定されたクラス名のある要素を取得します。
例えば、ページ全体の box
クラスが指定されている要素を取得するには、次のように記述します。
var boxes = document.getElementsByClassName('box');
タグの取得同様、DOMが取得されると、NodeListオブジェクトが返されます。
また、Elementオブジェクトからの実行も可能です。
<div id="page">
<p class="box">foo</p>
<p class="box">bar</p>
<p class="box">baz</p>
</div>
<p class="box">abc</p>
<p class="box">def</p>
<script>
var page = document.getElementById('page');
// id="page" 内の.boxを取得
var pageBoxes = page.getElementsByClassName('box');
console.log(pageBoxes.length); // 3
// ページ全体の.boxを取得
var boxes = document.getElementsByClassName('box');
console.log(boxes.length); // 5
</script>
クラス名を複数指定することも可能です。
クラス名とクラス名は半角スペースで区切ります。
<div id="page">
<p class="box">foo</p>
<p class="box special">bar</p>
<p class="box special">baz</p>
</div>
<script>
var page = document.getElementById('page');
// id="page" 内のpタグを取得
var pageBoxes = page.getElementsByClassName('box');
console.log(pageBoxes.length); // 3
// class="box special"を取得
var boxes = document.getElementsByClassName('box special');
console.log(boxes.length); // 2
</script>
この場合、取得される対象は、box
と special
両方が指定された要素になります。
どちらかに該当しても、対象にはならないので注意してください。
Selectors API で取得する
DOMのAPIにも、jQueryのようにCSSセレクタを指定することで要素を取得することができる仕組みがあります。
それが Selectors API です。
Selectors APIには2つのメソッドがあります。
- querySelector
1つの要素を取得する。複数該当する場合は、始めの1つを取得する。 - querySelectorAll
複数の要素を取得する。
他のメソッドと比較してみると、次のようになります。
var page1 = document.getElementById('page');
var page2 = document.querySelector('#page')
var paragraph1 = document.getElementsByTagName('p');
var paragraph2 = document.querySelectorAll('p');
var pageBoxes1 = document.getElementsByClassName('box');
var pageBoxes2 = document.querySelectorAll('box');
var selectors = document.querySelectorAll('div#contents > article .article-body a[href=#]');
一目瞭然、今まで紹介してきたメソッドよりも、柔軟にDOMを取得することが出来ます。
ただし、他のメソッドに比べて、Selectors APIを使用するほうが取得のパフォーマンスは劣ります。
以前、DOMの取得の際のパフォーマンスについて記事を書いていますので、参考にしてみてください。
また、Selectors APIで返されるのはNodeListオブジェクトではなく、StaticNodeListオブジェクトが返されます。
NodeListオブジェクトとStaticNodeListオブジェクトの違いは、オブジェクトに変更を加えた際に、HTMLに反映されるかどうかという違いです。
前回紹介した、ライブオブジェクトと関係している話ですが、
NodeListオブジェクトは取得後、オブジェクトに変更を加えればHTMLに反映されます。
しかし、StaticNodeListはオブジェクトに変更を加えても、HTMLに反映されません。
var paragraph = document.querySelectorAll('p');
for (var i = 0; i < paragraph.length; i++) {
paragraph[i].appendChild(document.createElement('span)); // Selectors APIでは無限ループにならない
}
他のメソッドではエラーだった、ループ処理ですが、Selectors APIを使うことで、正常に動作することから、
DOMツリーへの参照がされていないということがわかると思います。
この性質を理解しておくことで、思わぬアクシデントを回避できます。
次回に続きます。