要素を取得する
このレッスンで分かること
querySelectorは CSS のセレクタをそのまま使って、当たった要素を 1 つ返します- 全部ほしいときは
querySelectorAllで受け取り、forEachでまわします
まず掴まないと、何ひとつ変えられない
DOM の操作は、いつも同じ 2 段階でできています。掴む、そして変える。文字を変えるにも色を変えるにも、先に「どれを」を決めなければいけません。その「どれを」を決めるのが querySelector です。
JavaScript
const nav = document.querySelector(".site-nav");
nav.setAttribute("data-checked", "yes");
// <nav class="site-nav" data-checked="yes"> になるdocument はページ全体でした。そこから .site-nav に当たるものを探し、最初に見つかった 1 つを返します。丸かっこの中がそのまま CSS のセレクタなのがうれしいところです。タグ名なら "h2"、クラスなら ".hobby-item"、id なら "#about"。CSS で書いてきたとおりに当たります。ただし文字列なので、引用符で囲むのは忘れないでください。
2 行目の setAttribute は、要素に属性を 1 つ足す命令です。掴めたかどうかは目に見えないので、印を付けて確かめます。data- で始まる属性はデータ属性と呼ばれ、開発者が自由に付けてよい決まりです。見た目は変わりませんが、検証ツールの Elements タブを開けば、狙った要素にだけ印が付いているのが分かります。
4 つあるのに 1 つしか返ってこない
querySelector は、当たったうちの最初の 1 つしか返しません。趣味のリストには .hobby-item が 4 つありますが、返るのは「朝のさんぽ」だけです。
全部ほしいときは querySelectorAll を使います。返るのは NodeList という、当たった要素が順番に並んだものです。
JavaScript
const hobbies = document.querySelectorAll(".hobby-item");
console.log(hobbies.length); // 4
hobbies.forEach((hobby) => {
hobby.setAttribute("data-checked", "yes");
});NodeList は配列によく似ています。length があり、hobbies[0] で番号を指定でき、第6章で練習した forEach もそのまま効きます。ただし配列そのものではないので、map や filter は使えません。
| 書き方 | 返るもの | 見つからないとき |
|---|---|---|
querySelector(sel) | 最初に当たった要素 1 つ | null |
querySelectorAll(sel) | NodeList (0 個以上) | 空の NodeList |
getElementById(id) | id が一致する要素 1 つ | null |
getElementById は id 専用の古くからある書き方で、# を付けずに document.getElementById("about") と書きます。速さの差はこの規模では出ないので、どちらでも構いません。
綴りを間違えても、その行では止まらない
つまずきどころはここです。当たらなかったとき、querySelector はエラーを出さずに null を返します。エラーになるのは、その null を使おうとした次の行です。
JavaScript
const menu = document.querySelector(".site-navi"); // 綴りが違う
console.log(menu); // null
menu.setAttribute("data-checked", "yes"); // ここで TypeErrorコンソールには Cannot read properties of null と出ます。この文言を見たら、エラーが指す行ではなく、その要素を掴んだ行を疑ってください。セレクタの綴りが違うか、そもそも存在しないかのどちらかです。
当たるかどうかは、書く前に検証ツールで確かめられます。Elements タブで
Command + F(Windows はCtrl + F) を押してセレクタを打つと、当たった要素が光って件数も出ます。
よくある間違い
- セレクタの記号を忘れる — クラスなら
.、id なら#が要ります。querySelector("tagline")は<tagline>というタグを探しにいくので当たりません。逆にgetElementByIdでは#を付けません - NodeList に直接プロパティを書く —
hobbies.setAttribute(...)は入れ物への操作なのでTypeErrorです。用があるのは中身 1 つずつなので、forEachでまわしてから呼びます
課題
document.querySelector("h1")で見出しを掴み、setAttributeでdata-foundを"1"にする.taglineをquerySelectorで掴み、同じようにdata-foundを"1"にするdocument.getElementById("works")で作品セクションを掴み、data-foundを"1"にするquerySelectorAll(".work-card")で 3 枚のカードを掴み、forEachで 1 枚ずつdata-foundを"1"にする