##はじめに
JavaScriptでclassを取得してaddEventListener使ったら、エラーが出たので、自分なりに原因を突き止めてみました。
間違いや、補足知識などあればガンガンコメントしていただけると幸いです!
よろしくお願いします!
##前提として
今回、簡略化しわかりやすく説明するために、一部分のコードしか載せておりません。
しっかりと説明できるよう努めますのでよろしくお願いします。
問題が発生したコードの記述がこちらです↓
const studentName =document.getElementsByClassName("student_name");
studentName.addEventListener("click", function() {
// 以下省略
});
これは取得したclass名の要素をクリックしたら、イベント発火するように意図した記述となります。ちなみにこのclassで取得した要素は複数あります。
もちろん私は複数の要素全てにaddEventLisnerでイベント発火させたくてこの記述をしました。
しかし、うまく動きませんでした。。。
##原因と対策①
この原因はどうやらaddEventListenerは一つの要素にしかかけられないようです。
もし、複数の要素に対して、全てにこの効果を適応したい場合(今回のように定数に複数要素が格納されている場合)は繰り返し処理を行って、一つづつ要素を取り出して、一つづつ丁寧にaddEventListenerをかけてやります!
forEachを使って繰り返し処理を加えました↓
const studentName =document.getElementsByClassName("student_name");
studentName.forEach(function(student_name) {
student_name.addEventListener("click", function() {
// 以下省略
});
よし、これで全ての要素に対してイベント発火できる!と思ったのですが、また全然動きませんでした。一体どうして欲しいんだ。。。
##原因と対策②
原因としては、forEachメソッドは「HTMLCollection」に使えないことです。
どういうことかというと、getElementsByClassNameで所得した複数の値は、HTMLCollectionというものなのです。
そしてforEachはHTMLCollectionには使えないので、何も反応がなかったのです。
試しにブラウザ上でconsole.logでgetElementsByClassNameで所得した値を出力してみれば、HTMLCollectionと出てきます。
forEachは配列に対しては仕事をしてくれるらしいので力技でこいつを配列に変えます。
const studentName =document.getElementsByClassName("student_name");
const studentNames = Array.from(studentName);
studentNames.forEach(function(student_name) {
student_name.addEventListener("click", function() {
// 以下省略
});
2行目の記述でHTMLCollectionを配列に変えて、新しい定数studentNamesに代入しています。forEachを使う定数もstudentNamesに変更しました。
これで取得してきたすべての要素に対してaddEventListenerがイベント発火できるようになりました。
##おまけ
今回、getElementsByClassNameで取得してきた値はHTMLCollectionで返されていることを学びました。そしてforEachメソッドはそれに対しては使えません。
では同じようにclass名から要素を取得する方法として、querySelectorAllがありますが、この場合どうなるのでしょうか。
実際試してみました!
これが面白いことに、わざわざ配列に変更しなくても、addEventListenerを使うことができたのです。
調べたところ、querySelectorAllで取得すると、NodeListというもので返ってきます。
NodeListもHTMLCollectionと同様、複数の要素を格納しているようですが、配列とは別の存在です。だけど!NodeListにはforEachは使えました 笑
つまり、はじめからquerySelectorAllで取得すれば、「原因と対策②」で紹介したような、配列に直す作業はしなくて済みます。
こちらでclass名から取得する方法はgetElementsClassNameとは少し違いがありますのでお気をつけください。
↓こちらの記事を参照していただければと思います
HTMLを取得するメソッド三種
##終わりに
今回このエラーにハマって、新しく得られた学びがたくさんあってとても有意義な時間を過ごせました!そして、また、こうしてまとめて発信できる環境もあって本当にこの時代は恵まれているなーと感じます。