もりけん塾 JavaScript課題3 DOMを生成してHTMLに差し込む

もりけん塾 JavaScript課題3 DOMを生成してHTMLに差し込む

お題

なんとか、Gitの操作も慣れてきたところで、今回は課題2の応用です。

このDOM

<ul>
  <li><a href="a1.html"><img src="/img/bookmark.png">a1</a></li>
  <li><a href="a2.html"><img src="/img/message.png">a2</a></li>
</ul>

をJavaScriptでつくり、html内のulの中に差し込んでください

私の回答

ループ処理が必要であることは、なんとなく理解できましたが、ループ処理は for なんとかというコードを書くことくらいしか知りませんでした。

とりあえず、ループ処理について調べます。for, for of, for in, forEach(), reduce, mapなどなど、色々なループ処理があることを知りました。

初めは、使い方がまだよくわからなかったので、とりあえず、なんとなく見たことがあるという理由で、for文を使ってみることにしました。

最初のコード

最初に書いたコードはこちらです。

const ul = document.getElementById('js-list');
const imgSrc = ['./img/bookmark.png','./img/message.png'];
const aHref = ['a1.html','a2.html'];
const aText = ['a1','a2'];

for (let i= 0; i < imgSrc.length; i++){
    const li = document.createElement('li');

    const a = document.createElement('a');
    a.href = aHref[i];
    a.textContent = aText[i];

    const img = document.createElement('img');
    img.src = imgSrc[i];

    ul.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}

このコードで、プルリクエストしたところ、まずループ処理の中でappendChildを繰り返すと、パフォーマンスが落ちると教えて頂きました。そういうときは、document.createDocumentFragment()で空の要素を作成して、ループの中でfragmentに格納、そのあとulに追加する、という方がいいそうです。

2回目の修正

document.createDocumentFragment()を使って書いたコードがこちら。

const ul = document.getElementById('js-list');
const imgSrc = ['./img/bookmark.png','./img/message.png'];
const aHref = ['a1.html','a2.html'];
const aText = ['a1','a2'];

const fragment = document.createDocumentFragment();

for (let i= 0; i < imgSrc.length; i++){
    const li = document.createElement('li');

    const a = document.createElement('a');
    a.href = aHref[i];
    a.textContent = aText[i];

    const img = document.createElement('img');
    img.src = imgSrc[i];

    fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}
ul.appendChild(fragment);

const aHref = [‘a1.html’,’a2.html’];
const aText = [‘a1′,’a2’]; のところは、テンプレートリテラルを使うと、簡単ですよ!と教えて頂き、こちらについても調べました。

テンプレートリテラルは、文字列の中に、式をかけるのでとても便利です!

参考にしたサイト:

https://www.javadrive.jp/javascript/string/index5.html

最終的なコード

最終的なコードがこちら。

const ul = document.getElementById('js-list');
const imgSrc = ['./img/bookmark.png','./img/message.png'];

const fragment = document.createDocumentFragment();

for (let i= 0; i < imgSrc.length; i++){
    const li = document.createElement('li');

    const a = document.createElement('a');
    a.href = `a${i+1}.html`;
    a.textContent = `a${i+1}`;

    const img = document.createElement('img');
    img.src = imgSrc[i];

    fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}

ul.appendChild(fragment);

疑問だったこと

どこかで、ループの回数に数字を指定するコードを見たことがあったので、下記のコードだとだめなんですか?と質問しました。パッと見て、ループの回数がわかった方がわかりやすいのでは?と。

すると、下記のようなコードはマジックナンバーと呼ばれて、いい書き方ではないとの回答をもらいました。2がなんのことを指すのかわからないからです。

const liLength = 2;という感じで、変数に代入してから、for (let i= 0; i < liLength; i++){ …といった感じで使った方がいいと教えてもらいました。

for (let i= 0; i < 2; i++){
    const li = document.createElement('li');

    const a = document.createElement('a');
    a.href = aHref[i];
    a.textContent = aText[i];

    const img = document.createElement('img');
    img.src = imgSrc[i];

    fragment.appendChild(li).appendChild(a).insertAdjacentElement('afterbegin',img);
}

今回学んだこと

  • ループ処理の方法
  • document.createDocumentFragment()の使い方
  • テンプレートリテラルの使い方
  • 数字でループ処理の回数を書くのは、数字が何を表しているのかわかりにくい。変数に代入してから使う。

覚えることがたくさんですが、とても楽しい課題でした!

ループ処理は色々な方法がありますが、一体どれを使ったらいいの?と悩みました。もりけん先生によると、ループ処理の内容によりけりで、パフォーマンス、可読性、安全性のバランスをみて、決めるとのことでした。うーん、難しい。。

個人的には、そこまで処理速度が変わらないなら、for of 文が可読性高くて好き!となってます。

余談ですが、こちらのサイトでは、どのループ処理が処理速度が速いのかブラウザごとに比べる実験をされていて、興味深かったです。

https://dendenblog.xyz/javascript-fastest-loop/#for

次は課題4に挑戦!

私が所属しているフロントエンドエンジニアを目指す方のための塾 「もりけん塾」の森田賢二先生のTwitterはこちら!

先生のブログ「武骨日記」はこちら!

https://kenjimorita.jp/

まい

Webサービス制作会社で、Wordpressのテーマ開発や2Dシミュレーターの開発、JavaScriptを使用したフロントエンド周りの実装を担当しています。 JavaScriptが好きです。 最近は、3D Model Configuratorの制作にチャレンジしています。

もりけん塾カテゴリの最新記事