見様見真似でTODOリストを作ってみた(vanilla JS)

前提

先日UdemyのJavaScriptのコースを受講しおわり、とりあえず基礎知識は詰め込んだけど自分で1から書ける気は全くしなかったので、何か簡単なアプリを模写しながら作れないかなと考えました。

ちなみに受講しおわったUdemyのコースはこれ↓

The Complete JavaScript Course 2021: From Zero to Expert!

英語のコースだけど、字幕あるし、トランスクリプションってボタンを選択すれば、動画のスクリプト全部出るので、翻訳ソフトにコピペすれば大体分かります。ただ、コード書いてるところはコード模写して動かせば大体分かるけど、説明回はさすがに日本語のドキュメントも用意して照らし合わせしたほうが良いかも。

TODOリストである理由

これは単に、何かミニアプリを模写しようと思った時に、TODOリストはよく使う機能が集まってるからおすすめ、という話を聞いたからです。

やることを入力して、表示して、完了したら横線で消して、ゴミ箱にポイ。さらに、TODOリストはローカルストレージに保存して、ロードするたびにローカルストレージから呼び出して表示。確かによく使う処理が多いのかも?

ということで、参考というよりがっつり模写に使わせていただいた動画がこちら↓

つまずいた箇所

動画を見ながらだったので、わりとサクサク進む...と思いきや。

Uncaught TypeError: Cannot set property 'display' of undefinedで延々ハマった

JSファイルを間違いなくチュートリアル動画通りに書いてるのに、なぜか出るエラー↓

script.js:74 Uncaught TypeError: Cannot set property 'display' of undefined
        at script.js:74
        at NodeList.forEach (<anonymous>)
        at HTMLSelectElement.filterTodo (script.js:71)

See the Pen by yuii (@otomine) on CodePen.

原因はここでした↓

<ul class="todo-list">
</ul>

まさかのJSじゃなくHTMLという盲点。

簡単に説明すると、childNodesは、指定した要素の子要素を全て取得しているそうです。
ここでは省かれてるけど、ulタグの中にTODOリストは追加した数だけある。つまりchildNodesで取得しているのはこの↓部分(×TODOリストを追加した数)。

<div class="todo">
  <li class="todo-item">インプットしたTODOリスト</li>
  <button class="complete-btn">
      <i class="fas fa-check"></i>
  </button>
  <button class="trash-btn">
      <i class="fas fa-trash"></i>
  </button>
</div>

console.log(todo);で出してもちゃんと上のように出る。...と思いきや、 todoクラスのdivタグの前に、

#text

って出てたんですよね…

なんでだ???ってめちゃくちゃ調べまくったら、とてもアホなミス。

原因は、HTMLのul開始タグと閉じタグとの間に空白があったことで、その空白がNodeListに含まれていたためでした。

つまり、todosの中にはdivタグ以下は入っているものの、その前に空白が横入りしてたもので、display:flexはtodosの0番目の要素=空白(undefined)に付与しようとしていた、ということ。

噛み砕くと、そりゃエラーになるわ。って感じなんですが、書いてる時は全然わからなかったんですよね…

ちなみに、なぜか適用されてなかったコードフォーマッターを有効にし直したら、ちゃんとの間の空白は消えてました。

まとめ

  • NodeListで取得されるDOMツリーでは、空白はテキストとして扱われるので注意
  • コードフォーマッターは常に有効にしといたほうが良いかも