読者です 読者をやめる 読者になる 読者になる

tanaka's Programming Memo

プログラミングについてのメモ。

パーフェクトJavaScript勉強メモ(9)

前へ | 次へ

9章 DOM

DOMとは

DOM Level1
  • p246 Coreモジュール…HTMLに限らない一般的なDOM操作についての仕様
  • HTMLモジュール…HTML文章向けのメソッド
  • p247 getElementsByTagName…タグ名を指定して要素を取り出す
  • createElement…要素を作成
  • appendChild…要素を挿入
DOM Level2
  • IE8以下はDOM Level2に準拠せず
  • Core、HTMLモジュール…Level1の拡張
  • Views…文章の表示関連の仕様
  • Events…イベント関連
  • Style…スタイルシート関連
  • Traversal and Range…DOMツリーをたどる方法や範囲指定関連
DOM Level3
  • Core…拡張
  • Load and Save…文章の読み書きの仕様
  • Validation…文章構造の検証
  • XPathXPathについての仕様
  • Events…拡張。勧告段階ではないが、モダンブラウザには実装されている
DOM Level0
  • p248 DOMが規定される前にブラウザが実装していたもの
  • Window,Document,Navigator,Location,Historyなどが互換性のために残されている
  • DOM Level1で定義されたり、HTML5に組み込まれた
  • 名前の衝突を避けるため、Firefoxならmoz、Google ChromeSafariwebkitというプレフィックスをつける
DOMの記述

DOMの基礎

タグ、要素、ノード
  • タグとは、マークアップとして記述される文字列
  • p249 開始タグと終了タグがある
  • 要素、ノードは、継承関係にあり、ノードがスーパータイプ
  • ノードにはnodeTypeという属性があり、ELEMENT_NODE(ノードタイプの値が1)のものが要素になる
  • 要素はElement
  • 属性ノード(Attr),テキストノード(Text),コメントノード(Comment),文章ノード(Document)
DOM操作
Documentオブジェクト
  • DOMツリー構造のルートノード
  • 対応するHTMLタグはない。htmlタグやbodyタグは、DocumentオブジェクトのdocumentElementプロパティとbodyプロパティに対応
  • JavaScript内からdocumentでアクセスできる。windowのプロパティであり、windowはグローバルオブジェクトなので、windowは省略できる
  • windowオブジェクトはDOMツリー構造に含まれない

ノードの選択

IDによる検索
  • p250 document.getElementById(ID名)
  • IDはDOMツリーの中で一意にする。一意になっていない場合の挙動は規定されていない
タグ名による検索
  • p251 document.getElementsByTagName(タグ名)
  • タグ名に'*'を指定するとすべての要素を取得
  • Elementオブジェクトで量すると、そのElementオブジェクトの子孫ノードの中から見つける
  • ライブオブジェクトの特徴
    • getElementsByTagName()の結果は、NodeListオブジェクトで、配列ではないことに注意
    • NodeListオブジェクトはライブオブジェクトである
    • ライブオブジェクトとは、取得したタイミングの状況ではなく、常に現状に応じた変化を得られるオブジェクトである
  • p252 ライブオブジェクトを操作する上での注意点
    • ライブオブジェクトの要素数をループに使い、ループ内で要素を追加すると無限ループになるので注意
  • p253 ライブオブジェクトのパフォーマンス
    • パフォーマンス面では不利な実装
    • そのまま利用するより、一度Arrayに変換した方が速い
    • Array.prototype.slice()を使って、NodeListオブジェクトに対して適用する
var array = Array.prototype.slice.call(nodelist);
    • 以上で、nodelistをthisとしてsliceを実行すると、区切り文字がないのでそのまま配列として得られる
    • この方法はIE8以前には利用できない
    • IE8用のコーディング例
    • p254 NodeListの操作によるパフォーマンスの違い
    • 書籍の例では10倍ほど違う。書籍は2011年当時のものなので、最新でも試しておくとよい
    • p255 HTMLCollectionもライブオブジェクト。DOMLevel1で規定されているHTMLCollection一覧
    • ライブラリでArrayに変換するものもある。パフォーマンスが影響する部分は確かめるとよい
名前による検索
  • p256 HTMLDocument.getElementsByName(名前)で、name属性の値で取得可能
  • nameはformタグやinputタグで利用
  • それ以外は通常はid
クラス名による検索
  • HTMLElement.getElementsByClassName(クラス名)
  • 複数のクラス名を検索する場合は空白区切りで指定し、両方のクラスが指定されているものを抽出
  • HTML5で実装
  • IE8以前では使用できないが、汎用JavaScriptライブラリの多くで実装されているので、それを利用すると同等のことが可能
親、子、兄弟
  • p257 ノードは、関連する他のノードへの参照を持っている。一覧
  • 空白や改行もテキストノード
  • 可読性のために入れた改行や空白が取得されるので注意
  • p258 childNodesのオブジェクトはライブオブジェクト。大きくなりそうな場合はArrayへの変換を検討
  • 空白ノードを除外して列挙するAPIがブラウザに実装
  • IEは未対応の可能性がある
XPath
  • p260 複雑な条件での検索を可能にする
  • document.evaluate()を利用
  • p262 IEでは利用できない。IE9ではライブラリがある
Selectors API
  • XPathは複雑なので、かわりにCSSの指定方法が利用できる
  • document.querySelectorAll()で、指定の条件に合致するものを全て返す
  • document.querySelector()で、指定の条件に合致する最初の1つを返す
  • p263 Allの結果はStaticNodeListオブジェクト。このオブジェクトを変更しても、HTMLへの変更にはならないので注意

ノードの作成・追加

  • ノードの作成には、Document.createElement()、Document.createTextNode()、Document.createComment()を使う
  • 作成したノードを、Node.appendChild()や、Node.insertBefore()で、HTMLドキュメントに追加

ノードの内容変更

  • 取得したNodeListやNodeオブジェクトの内容を書き換える

ノードの削除

  • p264 Node.removeChild()を利用
  • 削除したいノードを取得して、取得したオブジェクト.parentNode.removeChild(取得したオブジェクト)で削除

innerHTML/textContent

innerHTML
  • 要素をまとめて変更したり追加するのに使える
  • Node.innerHTML()で、HTMLタグを直接指定して追加
  • HTML5の仕様。IEでも対応
textContent
  • 子要素も含めたテキスト部分だけ設定・取得できる
  • textContentに値を設定すると、子要素は全て削除されて、文字列だけ設定される
  • p265 IEではinnerTextプロパティ
  • DOM Level3 Coreにて定義
  • タグ指定しても、そのまま文字列として表示される

DOM操作のパフォーマンス

  • 個別にappendChild()などで追加すると、その度にブラウザが再描画される
  • document.createDocumentFragment()を利用すると、まとめた更新が可能
    • document.createDocumentFragment()でオブジェクトを生成
    • createElement()などでノードを作成して、fragmentにappendChild(作成したノード)する
    • 追加が終わったらappendChild(fragment)でまとめて追加する
    • (innerHTMLでよくない?)> 要パフォーマンスチェック

前へ | 次へ