banner
SlhwSR

SlhwSR

热爱技术的一名全栈开发者
github
bilibili

ブラウザのDOMオブジェクトを深く掘り下げる

一、DOM#

文書オブジェクトモデル (DOM) は HTMLXML 文書のプログラミングインターフェースです。

それは文書の構造化された表現を提供し、プログラムからその構造にアクセスして文書の構造、スタイル、内容を変更する方法を定義します。

任意の HTML または XML 文書は DOM を使用してノードで構成される階層構造として表現できます。

ノードは多くのタイプに分かれており、それぞれのタイプは文書内の異なる情報や(または)マークアップに対応し、独自の特性、データ、メソッドを持ち、他のタイプとの関係があります。以下のように示されます:

<html>
    <head>
        <title>ページ</title>
    </head>
    <body>
        <p>こんにちは世界!</p >
    </body>
</html>

DOM は原子が亜原子微粒子を含むように、多くのタイプの DOM ノードが他のタイプのノードを含んでいます。次に、その中の三つを見てみましょう:

<div>
    <p title="タイトル">
        コンテンツ
    </p >
</div>

上記の構造では、divp は要素ノードであり、コンテンツ はテキストノードであり、タイトル は属性ノードです。

二、操作#

日常のフロントエンド開発では、私たちは DOM 操作を欠かすことができません。

以前は、Jqueryzepto などのライブラリを使用して DOM を操作していましたが、その後 vueAngularReact などのフレームワークが登場し、私たちはデータを操作して DOM を制御することが多くなり、直接 DOM を操作することは少なくなりました。

しかし、これはネイティブ操作が重要でないことを意味するわけではありません。逆に、DOM 操作はフレームワークの深層の内容を理解するのに役立ちます。

以下に DOM の一般的な操作を分析します。主に次のように分かれます:

  • ノードの作成
  • ノードの取得
  • ノードの更新
  • ノードの追加
  • ノードの削除

ノードの作成#

createElement#

新しい要素を作成し、作成する要素のタグ名を受け取ります。

const divEl = document.createElement("div");

createTextNode#

テキストノードを作成します。

const textEl = document.createTextNode("コンテンツ");

createDocumentFragment#

文書の断片を作成するために使用されます。これは軽量の文書を表し、一時的なノードを格納し、文書の断片の内容を一度に DOM に追加するために主に使用されます。

const fragment = document.createDocumentFragment();

DocumentFragment ノードを文書ツリーに挿入しようとすると、挿入されるのは DocumentFragment 自体ではなく、そのすべての子孫ノードです。

createAttribute#

属性ノードを作成し、カスタム属性にすることができます。

const dataAttribute = document.createAttribute('custom');
console.log(dataAttribute);

ノードの取得#

querySelector#

任意の有効な css セレクタを渡すことで、単一の DOM 要素(最初のもの)を選択できます:

document.querySelector('.element')
document.querySelector('#element')
document.querySelector('div')
document.querySelector('[name="username"]')
document.querySelector('div + p > span')

ページ上に指定された要素がない場合、null を返します。

querySelectorAll#

ノードの子ツリー内のすべての一致する Element ノードのリストを返します。一致するものがない場合は、空のノードリストを返します。

const notLive = document.querySelectorAll("p");

注意が必要なのは、このメソッドが返すのは NodeList の静的インスタンスであり、静的な「スナップショット」であって「リアルタイム」のクエリではないということです。

DOM 要素を取得する方法には以下のようなものもありますが、すべてを述べることはしません。

document.getElementById('id属性値');指定されたidを持つオブジェクトの参照を返します。
document.getElementsByClassName('class属性値');指定されたclassを持つオブジェクトの集合を返します。
document.getElementsByTagName('タグ名');指定されたタグ名を持つオブジェクトの集合を返します。
document.getElementsByName('name属性値');指定された名前を持つオブジェクトの集合を返します。
document/element.querySelector('CSS選択子');最初の一致する要素のみを返します。
document/element.querySelectorAll('CSS選択子');すべての一致する要素を返します。
document.documentElement;ページ内のHTMLタグを取得します。
document.body;ページ内のBODYタグを取得します。
document.all[''];ページ内のすべての要素ノードのオブジェクト集合を取得します。

そのほか、各 DOM 要素には parentNodechildNodesfirstChildlastChildnextSiblingpreviousSibling 属性があり、関係図は以下のように示されます。

image

ノードの更新#

innerHTML#

DOM ノードのテキスト内容を変更するだけでなく、HTML フラグメントを介して DOM ノード内部の子ツリーを直接変更することもできます。

// <p id="p">...</p >を取得
var p = document.getElementById('p');
// テキストをabcに設定:
p.innerHTML = 'ABC'; // <p id="p">ABC</p >
// HTMLを設定:
p.innerHTML = 'ABC <span style="color:red">RED</span> XYZ';
// <p>...</p >の内部構造が変更されました

innerText、textContent#

文字列を自動的に HTML エンコードし、HTML タグを設定できないようにします。

// <p id="p-id">...</p >を取得
var p = document.getElementById('p-id');
// テキストを設定:
p.innerText = '<script>alert("Hi")</script>';
// HTMLが自動的にエンコードされ、<script>ノードを設定できません:
// <p id="p-id">&lt;script&gt;alert("Hi")&lt;/script&gt;</p >

両者の違いは、属性を読み取る際に innerText は隠れた要素のテキストを返さず、textContent はすべてのテキストを返すことです。

style#

DOM ノードの style 属性はすべての CSS に対応し、直接取得または設定できます。- に遭遇した場合はキャメルケースに変換する必要があります。

// <p id="p-id">...</p >を取得
const p = document.getElementById('p-id');
// CSSを設定:
p.style.color = '#ff0000';
p.style.fontSize = '20px'; // キャメルケース
p.style.paddingTop = '2em';

ノードの追加#

innerHTML#

この DOM ノードが空である場合、例えば <div></div> の場合、innerHTML = '<span>child</span>' を直接使用することで DOM ノードの内容を変更でき、新しい DOM ノードを追加したことになります。

この DOM ノードが空でない場合は、そうすることはできません。なぜなら innerHTML は元のすべての子ノードを直接置き換えてしまうからです。

appendChild#

子ノードを親ノードの最後の子ノードとして追加します。

例を挙げると:

<!-- HTML構造 -->
<p id="js">JavaScript</p >
<div id="list">
    <p id="java">Java</p >
    <p id="python">Python</p >
    <p id="scheme">Scheme</p >
</div>

p 要素を追加します。

const js = document.getElementById('js')
js.innerHTML = "JavaScript"
const list = document.getElementById('list');
list.appendChild(js);

現在の HTML 構造は以下のようになります。

<!-- HTML構造 -->
<div id="list">
    <p id="java">Java</p >
    <p id="python">Python</p >
    <p id="scheme">Scheme</p >
    <p id="js">JavaScript</p >  <!-- 追加された要素 -->
</div>

上記のコードでは、DOM 要素を取得してから追加操作を行っています。この js ノードはすでに現在の文書ツリーに存在しているため、このノードはまず元の位置から削除され、新しい位置に挿入されます。

新しいノードを動的に追加する場合は、まず新しいノードを作成し、指定された位置に挿入します。

const list = document.getElementById('list');
const haskell = document.createElement('p');
haskell.id = 'haskell';
haskell.innerText = 'Haskell';
list.appendChild(haskell);

insertBefore#

子ノードを指定された位置に挿入します。使用方法は以下の通りです:

parentElement.insertBefore(newElement, referenceElement)

子ノードは referenceElement の前に挿入されます。

setAttribute#

指定された要素に属性ノードを追加し、要素にその属性がすでに存在する場合は属性値を変更します。

const div = document.getElementById('id')
div.setAttribute('class', 'white');//最初のパラメータは属性名、二番目のパラメータは属性値です。

ノードの削除#

ノードを削除するには、まずそのノード自体とその親ノードを取得し、親ノードの removeChild を呼び出して自分自身を削除します。

// 削除対象のノードを取得:
const self = document.getElementById('to-be-removed');
// 親ノードを取得:
const parent = self.parentElement;
// 削除:
const removed = parent.removeChild(self);
removed === self; // true

削除されたノードは文書ツリーには存在しなくなりますが、実際にはメモリ内に残っており、いつでも別の場所に再度追加できます。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。