はじめに
こんにちは。新卒でエンジニアをしています、木村と申します。
以前イベントリスナーのコピーを行いたい場面があり、結論「この環境ではできない」という形にはなったのですが、その過程で調べたことをまとめました。イベントはフロントエンドの開発をしていると結構な頻度で出てきたのでなんとなく「こんなもの」という認識でいましたが、きちんと理解できていなかった部分も多かったので、基礎からの記事になりますがよろしくお願いいたします。
そもそもイベントって何
イベント
プログラム動作中に起きる出来事を指します。
- クリック
- 文字入力
- データを送信
- ページの読み込み etc…
イベントハンドラ
イベントが発火した時に実行されるコードのブロックです。イベントに応答して実行されるように設定されている場合、イベントハンドラを登録しているといいます。
イベントリスナーと呼ばれることがありますが、厳密には別のもので、イベントに応答して動作する処理自体を指します。
イベントリスナー
イベントの発生を待ち受けるもの(仕組み)です。通常よく使われている.addEventListener()
メソッドで行っているのが、この仕組みを要素に付与することです。
イベントリスナーの追加
イベントリスナーを登録する方法として、イベントハンドラープロパティと.addEventListener()
があります。
イベントハンドラープロパティ
イベントを発行することができるオブジェクト(ボタンなど)が持つ、イベントハンドラープロパティです。例えば、クリックに応じて処理を行いたいときはonclick
を使用します。
const btn = document.querySelector("button"); btn.onclick = () => { alert('ボタンクリック!') };
onclickではひとつのイベントにつき一つのハンドラーのみ追加できます。
element.onclick = function1; element.onclick = function2;
上記のように設定した時、function1はfunction2に上書きされ、ボタンが押された時にfunction2 のみが実行されます。
See the Pen
onClick by Kimura (@Kinaka)
on CodePen.
.addEventListener
onclick
では一つのハンドラーしか追加できないのに対し、addEventListener
では複数のハンドラーを追加することができます。
element.addEventListener("click", function1); element.addEventListener("click", function2);
この場合、ボタンがクリックされた時にfunction1もfunction2も実行されます。
See the Pen
addEventListener by Kimura (@Kinaka)
on CodePen.
※React
Reactでは、JSのonClick
のように直接イベントハンドラを登録するのではなく、propsとして渡しています。
export default function Button() { function handleClick() { alert('ボタンクリック!'); } return ( <button onClick={handleClick}> ボタン </button> ); }
このとき、作成されたhandleClick
関数はイベントハンドラで、これをコンポーネントにpropsの一部として渡しています。そしてpropsとして渡されたonClick
をonClick={onClick}
としてブラウザの組み込み要素(例えばボタン)に渡しています。
(自分はJSの.onClick
と全く同じようなものだと思っていました💦)
イベントリスナーの取得
イベントリスナーのコピー行う方法が分からず詰まってしまったのですが、調べた限りバニラJSではできない、という風に判断しました。いい方法をご存じの方は教えていただきたいです。
先述の条件でなければ、似たような方法があるようでしたのでそれをまとめます。
.clone()(jQuery)
$("複製する要素のセレクタ").clone(true)
jQueryを使用するとイベントハンドラごとコピーすることができます。
要素と共にイベントハンドラーをコピーするかどうかを示すboolean値でtrueを指定することが必要です。
iimonのホームページ(https://iimon.co.jp/)で確認してみます。
「詳しく見る」のボタンにホバーしたときにログを出すイベントハンドラーを追加し、その要素をイベントハンドラーごとコピーしてオリジナルのボタンの下に設置します。
どちらのボタンの上にカーソルを置いてもコンソールで「ホバーされました」と表示されるのが確認できます。イベントハンドラーごとコピーできているようです。
// jQueryを使ってボタン要素を取得 const $button = $('#top_service .common_btn'); $button.on('mouseover', () => { console.log('ホバーされました'); }); // jQueryを使って要素を複製し、イベントリスナーも一緒にコピー $button.clone(true).appendTo('#top_service');
getEventListeners(object) (ChromeDevToolsのみ)
指定されたオブジェクトに登録されているイベントリスナーを取得します。
iimonのホームページ(https://iimon.co.jp/)で以下のコードをコンソールで入力すると、「詳しく見る」のボタンにホバーしたときにログを出すイベントハンドラーを、getEventListenerで確認できます。
ただし、デベロッパーツールのみで使うことが出来るので本番環境では使用はできません。
const button = document.querySelector('#top_service .common_btn'); const function1 = ()=>{console.log('ホバーされました')} button.addEventListener('mouseover', function1) getEventListeners(button);
jQueryでできるのにバニラJSで出来ないんだと驚きました。
この記事を読んで興味を持って下さった方がいらっしゃればカジュアルにお話させていただきたく、是非ご応募をお願いします!