JavaScript入門 イベント伝搬を利用してToDoリストに取り消し線を追加削除する方法を徹底解説!
今回はJavaScriptのDOMを操作して、ToDoリストに取り消し線を入れる方法を解説します。
DOMとは「Document Object Model」の略でJavaScriptでhtmlの要素を操作するための仕組みのことです。
このDOMを操作することで、ToDoリストをクリックするたびに取り消し線を入れたり削除したりすることができるようになります。
たとえば以下の図のようにします。
それでは詳しく解説していきますね。
HTML
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8">
<title>ToDoリスト</title>
<link rel="stylesheet" href="css/style.css">
</head>
<body>
<style>
.done {
text-decoration: line-through;
}
</style>
</head>
<body>
<ul> <!-- e.currentTarget -->
<li>プログラミングを勉強する</li>
<li>本を読む</li> <!-- e.target -->
<li>ブログを書く</li>
</ul>
<script src="js/main.js"></script>
</body>
</html>
JavaScript
document.querySelector('ul').addEventListener('click', e => {
if (e.target.nodeName === 'LI') {
e.target.classList.toggle('done');
}
});
上記のJavaScriptの記述はイベント伝搬というJavaScriptの仕組みを利用して記述しています。
イベント伝搬とは?
イベント伝搬とは子ノードで発生したイベントが親ノードへと波紋のように伝わっていく仕組みです。
今回の場合は子ノードであるliノードをクリックすると親ノードであるulノードに伝わっていきます。もちろんbodyにも伝わっていきます。
では、なぜこのイベント伝搬を使って記述するのかというと、記述量が少なくて済からです。
たとえばイベント伝搬を利用せずに記述すると以下のようになります。
document.querySelectorAll('li')[0].addEventListener('click', e => {
e.target.classList.toggle('done');
});//プログラミングを勉強する
document.querySelectorAll('li')[1].addEventListener('click', e => {
e.target.classList.toggle('done');
});//本を読む
document.querySelectorAll('li')[2].addEventListener('click', e => {
e.target.classList.toggle('done');
});//ブログを書く
今回はToDoリストに3つしか入れてないので、少ないように見えますがToDoリストが増えれば増えるだけ記述量が増えてしまいます。
イベント伝搬を使えばどれだけToDoリストが増えても記述量は同じなのです。
JavaScriptの解説
それではJavaScriptを上から順に解説していきますね。
document.querySelector('ul').addEventListener('click', e => {
});
上記の記述はliノードをクリックしてもイベントの伝搬でクリックしたというイベント情報がulノードまで伝わってきますので、ulノードにクリックした情報が伝わってきたらという意味になります。
document.querySelector('ul')ですが、document(html)内を探してquerySelector("ul")でhtmlのulタグを選んできます。
※ ()内は文字列で記述する。
addEventListener("click", ()=> { //この中にクリックしたあとの処理を記述します。});はイベントに合わせて実行させる関数で、第1引数にイベント名を記述し、第2引数に関数を記述します。
今回の場合はイベント名にクリックしたあとを実行したいので、イベント名には"click"を記述します。タブルクォーテーションかシングルクォーテーションで囲んでくださいね。
クリック以外のイベントにはマウスホバーやキーボード入力など、さまざまあります。
第2引数の関数は記述の短いアロー関数で記述し、引数名にeventのeを入れてあげます。関数名がないのはクリックしたら関数を呼び出すことができるので関数名はありません。
この引数名eにはイベントに関する情報が入っており、これはブラウザが自動的に渡してくれます。
if (e.target.nodeName === 'LI') { }
次のif (e.target.nodeName === 'LI') { }は「もし、クリックしたノードがliノードだったら」という意味になります。
ちなみにLIが大文字なのはliのノードネームが大文字で表すからです。
以下のコードを入力してliノードをクリックしてみてくだい。
そうするとコンソールにLIと表示されます。
document.querySelector('ul').addEventListener('click', e => {
if (e.target.nodeName === 'LI') {
e.target.classList.toggle('done');
}
console.log(e.target.tagName);
});
}
詳しくはMDNのElement.tagNameを参照してみてください。
そして、なぜこのif文を記述するのかというと、liノードではないところをクリックしても打消し線のon,offができてしまうからです。
たとえば以下の赤枠をクリックしてみてください。
赤枠の部分は親要素であるulノードがありますので、そこをクリックすると3箇所に打消し線が入ってしまうのです。
e.target.classList.toggle('done');
次にe.target.classList.toggle('done');ですが、targetとは実際にクリックされた要素は Event オブジェクトの targetで取得することができます。
よってe.targetとすることで、eはクリックしたイベントの情報が入っているためliノードをクリックした場合となります。
そしてclassListはクラス名を追加したり、削除したり、参照したりすることが出来る便利なプロパティでclassListの後ろにメソッドを定義することができるので今回はtoggleメソッドを使い()内はクラス名を入れます。
toggleメソッドはON・OFFを切り替えることができるメソッドです。
イベント伝搬を止める方法!
子要素であるliノードをクリックすると親要素であるulノードに伝わってくると解説しましたが、実際に伝わっているのかを確認してみましょう!
以下のように記述してみてください。
document.querySelector('ul').addEventListener('click', e => {
if (e.target.nodeName === 'LI') {
e.target.classList.toggle('done');
}
});
document.querySelector('li').addEventListener('click', e => {
alert("li がクリックされたよ。");
});
ブラウザで一番上のリストである「プログラミングを勉強する」をクリックして見ください。
そうするとアラートが表示されたあとに打ち消し線もでます。
これはulノードに伝搬されているからですね。
次に伝搬されることを防ぐコードを記述してみましょう。
先程のコードにe.stopPropagation();を追加します。
propagationの意味は伝搬という意味です。
document.querySelector('ul').addEventListener('click', e => {
if (e.target.nodeName === 'LI') {
e.target.classList.toggle('done');
}
});
document.querySelector('li').addEventListener('click', e => {
e.stopPropagation();
alert("li がクリックされたよ。");
});
こうするとアラートが出たあとに打消し線がつかなくなるはずです。
これによって伝搬されていることがわかったと思います。
まとめ
1.liノードをクリックすると伝搬によって親要素であるulノードに伝わります。
2.ulノードがにクリックしたという情報が伝わってきたら、if文の記述でクリックしたノードがliノードの場合を実行します。
3.クリックしたliノードにクラス名であるdoneクラスを実行してください、という流れでした。
最後まで読んでいただきありがとうございました。