[JS]getElementsByClassNameで取得してきた複数の要素をforEachでループ処理する
ども、むったん(@6ttan)です。
先日、先輩にコードレビューをしてもらった際に「forEachでループ処理した方がラクだよ」と教えてもらったので、早速使ってみたところ変なループの仕方をしてたので備忘録も兼ねて残しておきます。
…結論として、for文で言う条件式と加算式を忘れていたのが主な原因だったんですがね。
コード&デモ
NewsエリアとInformationエリアにSpring、Summer、Autumn、WinterのテキストをJSから出力しています。
用途としては、数ヶ月分のカレンダーだったり、重要な情報だったり…「複数箇所に出力したいけど、まとめて一箇所で管理したーい!😱」なんて時に使えるのではないでしょうか?
ちなみに私がこれを作った要因も、「複数箇所に同じコンテンツ(過去数ヶ月分の在庫状況表示)を表示して欲しい」という要望からでした。
コード&解説
まずHTMLです。
<main>
<div id="news">
<p>News</p>
<ul class="notice__box js-noticeList">
<li class="notices"></li>
<li class="notices"></li>
<li class="notices"></li>
<li class="notices"></li>
</ul>
</div>
<div id="about">
<p>About</p>
</div>
<div id="pickup">
<p>Pickup</p>
</div>
<div id="information">
<p>Informaiton</p>
<ul class="notice__box js-noticeList">
<li class="notices"></li>
<li class="notices"></li>
<li class="notices"></li>
<li class="notices"></li>
</ul>
</div>
</main>
今回は<li class=”notices”></li>内にJSでテキストを出力していきます。
次にJSは以下になります。
let notice = ['Spring', 'Summer', 'Autumn', 'Winter'];
let n = 0;
let i = 0;
let targetParent = Array.from(document.querySelectorAll('.js-noticeList'));
targetParent.forEach(function () {
let targetList = Array.from(targetParent[n].querySelectorAll('li'));
targetList.forEach(function () {
if (i == notice.length) {
i = 0;
}
targetList[i].innerHTML = notice[i];
i++;
});
n++;
});
cssはCodepenの方をご覧ください。
コード解説
まず、JSの4行目です。
let targetParent = Array.from(document.querySelectorAll('.js-noticeList'));
HTML内の.js-noticeListをすべて取得して配列にしてくれ!としています。
そしてHTML内には.js-noticeListが2つあるので、targetParentに.js-noticeListが配列として2つ格納されています。
次に6行目です。
targetParent.forEach(function () {
~
)};
はい、出ましたforEach!
なにも気にしなければtargetParentに格納されている分の2回がブンブンとループ処理してくれます。
なので.js-noticeListを2回ブンブンしてくれます←
でもnoticeにセットした四季名を出力したいのは孫要素にあたるliなんです。
あと4回…いや、計8回ループしてもらいたいんです。
なので7行目のを行います。
let targetList = Array.from(targetParent[n].querySelectorAll('li'));
n個目の.js-noticeList内にあるliをすべて取得して配列にしてくれ!としています。
なんでn個目かというと、1個目の.js-noticeListのliたち→2個目の.js-noticeListのliたちとしてあげないとundefindが出た…(気がした)
もしくは1個目の方で8回ループとか…
ひとまずカオスで泣いた記憶しかない😭
次に14行目、targetListに格納したn個目の.js-noticeList内にあるli配列を
targetList.forEach(function () {
~
)};
で格納されてるli分(ここでは4回)ブンブン回します。
特殊なことをしなければ14〜15行目の
targetList[i].innerHTML = notice[i];
i++;
で、i個目のtargetList…つまりliですね、こちらの要素の内容を書き換えていきます(書き換え…出力の方が個人的にはしっくりくる)
ただし今回は、iが4になったとき…2個目の.js-noticeListの1番目のliのときに、noticeに格納されている5番目(0番目がSpring)が存在しません。
なので、10〜12行で
if (i == notice.length) {
i = 0;
}
で、出力するnoticeのリセットをしています。
notice.lengthは4だから、iが4だったら0にして2個目の.js-noticeListの1番目のliに0番目のSpringから書き換えを行っています。
全体の動き
全体の動作をざっくり書き出すと…
- HTML内から.js-noticeListを探す
- .js-noticeListの個数分forEachを回す
- .js-noticeList内からliを探す
- liの個数分forEachを回す
- iの数字をチェック
- liにnoticeの配列を順番に出力する
- iを加算して、次の配列を出力できるようにする…を4回分ブンブン
- 4回まわしたらnを加算して、2個目の.js-noticeListに同様の処理をする
と、言う感じです。
ではでは👋