JavaScript入門:プロフィールサイトを動かす

DOM とは何か

生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア
編集 LuaGate編集部

このレッスンで分かること

  • ブラウザが HTML の文字列をどうやってオブジェクトの木に変えるのか
  • document が何を指しているのか
  • 検証ツールの Elements タブで DOM を確かめる手順

DOM とは何か とは

DOM はブラウザが HTML を読み込んでつくる、ページの中身を表したオブジェクトの木です。JavaScript はこの木を通してページを読み書きします。

ここまでとここからの違い

第7章までに書いてきた JavaScript は、文字と数と配列とオブジェクトを組み立てるだけのものでした。console.log に出した結果は、開発者だけが見るコンソールに並びます。ページを開いた人には何も見えません。

第8章からは違います。書いた JavaScript が、目の前のページそのものを書きかえます。肩書きの文字が変わり、作品カードが増え、色が変わる。このコースの看板である「DOM を操作してページを書き換えられる」を、ここから 7 回かけて実際に達成します。

そのために、まず「JavaScript から HTML がどう見えているのか」を知る必要があります。ここを飛ばして querySelector の書き方だけ覚えると、うまく動かないときに何を疑えばいいのか分からなくなります。

HTML は文字列のまま扱われていない

ブラウザがサーバーから受け取るのは、ただの長い文字列です。次のような文字が、上から順番に届きます。

// ブラウザが受け取るもの (中身はただの文字列) '<h1>山田 太郎</h1><p class="tagline">Web エンジニアを目指しています</p>'

ブラウザはこの文字列を先頭から読み、タグの開きと閉じを見て、どれが誰の中に入っているかを組み立てます。この作業をパースと呼びます。パースの結果できあがるのが DOM です。DOM は Document Object Model の頭文字で、日本語にすると「書類をオブジェクトとして表したもの」になります。

diagram (will load when visible)

大事なのは矢印の向きです。画面は DOM から描かれます。JavaScript が触るのも DOM です。つまり JavaScript が DOM を変えれば、画面もそれに合わせて描き直されます。HTML ファイルの中身を書きかえているわけではありません。ページを再読み込みすれば、JavaScript が変えたぶんは消えて、元の HTML から DOM が組み直されます。

ブラウザで「ページのソースを表示」すると、JavaScript で書きかえたあとでも元の HTML が出てきます。検証ツールの Elements タブに出るのは、いまの DOM です。この 2 つは別物です。

木の形になっている

DOM は入れ子のとおりに親と子の関係を持ちます。プロフィールサイトの上のほうを取り出すと、次のような形です。

// 親子の関係を字下げで表すとこうなる document └ html ├ head └ body ├ header.site-header │ ├ h1 │ ├ p.tagline │ └ nav.site-nav └ main.site-main

いちばん上にいるのが document です。document はページ 1 枚ぶん全体を表すオブジェクトで、ブラウザがあらかじめ用意してくれています。自分で const document = ... と書く必要はありません。console.log と同じで、書けばそこにあります。

木の一つひとつの節をノードと呼びます。ノードにはタグでできた要素ノード、文字だけのテキストノード、<!-- --> のコメントノードなどがあります。この章で扱うのはほとんどが要素ノードです。

要素ノードは、第7章で書いたオブジェクトとよく似ています。プロパティを持っていて、ドットでつなげば読み書きできます。違うのは、値を書きかえた瞬間にブラウザが画面を描き直してくれるところです。

// 要素はオブジェクト。プロパティを持っている const el = document.querySelector("h1"); console.log(el.tagName); // "H1" console.log(el.textContent); // "山田 太郎"

つまり、これまで練習してきたオブジェクトの読み書きが、そのまま画面の操作になります。新しい文法をたくさん覚えるわけではありません。覚えるのは「どのプロパティを触ると何が変わるか」だけです。

呼び名何を指すか
documentページ全体document.querySelector(...) の入口
要素ノードタグ 1 つぶんh1 div.work-card
テキストノードタグの中の文字山田 太郎
親 / 子入れ子の上下header の子が h1
兄弟同じ親を持つ並びh1p.tagline

検証ツールで木を見る

概念の話はここまでです。実物を見たほうが早いので、自分のプロフィールサイトを開いて確かめます。手順は次のとおりです。

  1. できあがったプロフィールサイトをブラウザで開く
  2. ページのどこかを右クリックして「検証」を選ぶ (Mac は Command + Option + I、Windows は F12 でも開く)
  3. 上のタブから Elements を選ぶ
  4. <body> の左にある三角形をクリックして開く
  5. <header class="site-header"> を開き、その中に <h1><p class="tagline"> が並んでいるのを確かめる
  6. <h1> の行にマウスを乗せると、画面のほうで名前の部分が青く光る。木の 1 行が画面のどこなのかが分かる
  7. #works の中の <div class="work-list"> を開き、<article class="work-card"> が 3 つ並んでいるのを数える

この 3 つの article が、これから JavaScript で増やしたり作り直したりする相手です。

もう 1 つ試してほしいことがあります。検証ツールの Console タブを開いて、次の 1 行を打って Enter を押してみてください。

document.querySelector("h1")

<h1>山田 太郎</h1> と返ってきます。Elements タブで青く光っていたあの行が、コンソールから 1 行で取り出せました。次の回でやるのは、まさにこれです。コンソールは書いたそばから結果が返るので、書き方を確かめる場所として便利です。うまく動かないときは、まずコンソールで 1 行ずつ試すのが近道になります。

検証ツールの Elements タブでは、その場でタグや文字を書きかえられます。書きかえると画面がすぐ変わります。これは手で DOM を触っているのと同じことで、JavaScript がやることを人の手でやっているだけです。再読み込みすれば元に戻るので、こわがらずに試して大丈夫です。

この章で進めること

次の回から、この DOM を JavaScript で触っていきます。進み方は次のとおりです。

  • 掴む … querySelector でほしい要素を 1 つ取り出す
  • 変える … textContent で文字を、classList で見た目を差し替える
  • 増やす … createElementappend で新しい要素をつくって木に足す
  • まわす … 作品の配列から、カードを必要なだけ量産する

最後の回で、作品ギャラリーは HTML に直接書いた 3 枚から、配列を直せば画面が変わる状態になります。データと見た目を分けるという、実際の Web 開発で毎日使われている考え方です。

よくある間違い

HTML ファイルが書きかわると思ってしまう

JavaScript が変えるのは、いまブラウザの中にある DOM だけです。次のコードで肩書きを変えても、index.html の中身は 1 文字も変わりません。

// 画面の文字は変わる。ファイルの中身は変わらない document.querySelector(".tagline").textContent = "変えました";

保存したいなら、あとの章で出てくる localStorage のような仕組みが必要になります。

document を自分でつくろうとする

document はブラウザが用意している変数です。次のように書くと、もともとあるものを上書きしてしまい、以降の DOM 操作が全部おかしくなります。

// これは書かない const document = {};

同じ理由で、windowhistory のような名前も自分の変数には使わないようにします。

ソース表示と Elements タブを同じものだと思う

「ソースの表示」は、サーバーから届いた元の HTML です。「Elements」は、いまの DOM です。JavaScript で足したカードはソース表示には出てきません。動いているかどうかを確かめるときは、必ず Elements タブのほうを見ます。

復習ミニクイズ

ブラウザで JavaScript が `document.querySelector("h1").textContent = "変更"` を実行しました。このあと「ページのソースを表示」で見える HTML はどうなっていますか