はじめに
前提
まず前提として、この記事を書いているのは未経験からプログラミングに挑戦中の者になります。学習はフィヨルドブートキャンプに参加しながら取り組んでいて、現役のエンジニアの方からレビューをもらいながら進めています。
現在の学習状況は以下を随時更新しているので興味ある方はご覧ください。
hirano-vm4.hatenablog.com
筆者は執筆時点で、Ruby(Ruby on Rails)のプラクティスが終わったあとにJavaScriptに取り組んでいるので、完全に0からではありません。JavaScriptを多言語から学ぶにあたって、まず覚えるべき要点をまとめました。
詳しい解説ではなく要点をまとめた学習記録・ノートになりますのでご注意ください。
記事の本体は以下にになります。長くなってしまったので別記事として書いているものとなります。ご注意ください。
hirano-vm4.hatenablog.com
イベント処理
input 要素でマウスでクリックしたときに実行するイベントハンドラを登録する場合
<input type="button" value="button" onclick="イベントハンドラ">
<body>
<p>ボタンをクリック</p>
<input type="button" value="button" onclick="alert('こんな感じ')" />
</body>
イベントの種類の一覧
属性 |
イベントの種類 |
onclick |
マウスのボタンが要素の上でクリックされたとき |
oncontextmenu |
マウスが右クリックされたとき |
ondblclick |
マウスのボタンが要素の上でダブルクリックされたとき |
onmousedown |
マウスが要素の上で押されているとき |
onmouseup |
マウスのボタンが要素の上で離されたとき |
onmousemove |
マウスが要素の上を移動しているとき |
onmouseover |
マウスがリスナーが接続されている要素または子要素に移動したとき |
onmouseout |
マウスがリスナーが接続されている要素または子要素から外れたとき |
onselect |
テキストが選択されているとき |
onwheel |
マウスホイールが回転しているとき |
onauxclick |
マウスのメイン以外のボタン(中央のボタンなど)が要素の上でクリックされたとき |
onkeydown |
いずれかのキーが押されたとき |
onkeyup |
いずれかのキーが離されたとき |
onkeypress |
いずれかのキーが押された状態にあるとき |
onblur |
要素がフォーカスを失ったとき(バブリングなし) |
onfocus |
要素がフォーカスを受け取ったとき(バブリングなし) |
onchange |
要素の値の変更が確定したとき(<input>, <select>, <textarea> ) |
oninput |
要素の値が変更したとき(<input>, <select>, <textarea> ) |
onsubmit |
サブミットボタンが押されたとき |
onreset |
リセットボタンが押されたとき |
onload |
ページ全体がスタイルシートや画像などのすべて読み込まれたとき |
onabort |
エラー以外の原因で読み込みが中止されたとき |
onerror |
エラーが発生して読み込みが失敗したとき |
バブリング・キャプチャリングとは?
ウェブページ上にユーザーが何かイベントをトリガーしたとき(例:ボタンをクリック・要素にマウスを載せるなど)、そのイベントはHTML要素のツリー構造をたどって(例:イベントが発生した要素の親要素である div 要素から、 body 要素、 html 要素、 Document オブジェクト、 Window オブジェクトまで DOM ツリーを上へ向かって順番に click イベントが発生)下から上へ伝播することを「バブリング」と呼ぶ。
- イベントは通常、ユーザーの操作が行われた要素から親要素、さらに祖父要素へと伝播する
- 親要素から子要素への逆伝播はキャプチャリングという
- イベントは要素の境界を超え、親要素にも伝播する。親要素でイベントハンドラを設定されている場合、そのハンドラも実行される
- バブリングはイベントハンドリングの一貫性を提供する。親要素で1つのイベントハンドラを設定することで、子要素すべてに対して同じ処理を行えて、コードの効率性と保守性に役立つ
DOMで取得した要素のプロパティにイベントハンドラを登録
要素オブジェクトのプロパティにイベントハンドラを登録
これまでの例ではHTMLの中でイベントハンドラを設定していたが、DOMを使用して任意の要素オブジェクトとして取得。その要素オブジェクトに対してイベントハンドラを設定できる。
<body>
<input type="button" value="button" id="test" />
<script>
const buttonClick = () => {
alert("これを表示させる");
};
let button = document.getElementById("test");
button.onclick = buttonClick;
</script>
</body>
- プロパティにイベントハンドラを設定する場合は、イベントが発生した時に呼び出されるコールバック関数を設定
- click イベントに対してコールバック関数の buttonClick 関数を設定している
- コールバック関数を設定するときには、関数名だけを記述する
<script>
const buttonClick = () => {
let day = new Date();
alert(day);
};
let button = document.getElementById("test");
button.onclick = buttonClick;
</script>
</body>
イベントハンドラを無名関数やアロー関数を使って記述
イベントハンドラとして登録するコールバック関数は、無名関数を使って記述することもできる。
<script>
let button = document.getElementById("test");
button.onclick = function () {
let day = new Date();
alert(day);
};
</script>
button.onclick = null;
<script>
let button = document.getElementById("test");
button.onclick = function () {
let day = new Date();
alert(day);
this.onclick = null;
};
</script>
こうすると1度アラートが表示され、二回目以降は何も起こらなくなる。
※無名関数の場合、関数内で this を参照するとイベントが発生した要素が格納されている
コールバック関数が呼び出される時にイベントの情報を受け取る
- イベントが発生してコールバック関数が呼ばれるときに発生したイベントに関する情報が格納された Event オブジェクトが引数として渡されてくる
- イベントに関する情報を関数内で利用する場合は、コールバック関数で引数を記述する
<script>
function butotnClick(event){
}
let button = document.getElementById('test');
button.onclick = butotnClick;
</script>
使用例
<body>
<p>ボタンをクリックしてください。</p>
<input type="button" value="button" id="test" />
<script>
let button = document.getElementById("test");
button.onclick = function (event) {
console.log("eventのタイプ " + event.type);
console.log("eventのターゲット " + event.target);
};
</script>
</body>
addEventListenerメソッドを使ってイベントリスナーを登録
addEventListener
メソッドを使用してイベントに対して登録した関数のことを特にイベントリスナーと呼ぶ
target.addEventListener(type, callback [, options])
- 第一引数にはイベントの種類を表す文字列を指定(clickなどなど)
- 第二引数にはイベントハンドラとしてコールバック関数を指定
- 第さん引数にはオプション
<input type="button" value="button" id="test">
<script>
function butotnClick(){
console.log('お買い上げありがとうございます');
}
let button = document.getElementById('test');
button.addEventListener('click', butotnClick);
</script>
idテストのボタンをユーザーがクリックしたあら、コールバック関数であるbutotnClickが呼び出されます。
<input type="button" value="button" id="test" />
<script>
let button = document.getElementById("test");
button.addEventListener("click", function () {
console.log("テストします");
});
</script>
<input type="button" value="button" id="test" />
<script>
let button = document.getElementById("test");
button.addEventListener("click", () => {
console.log("テストします");
});
</script>
同じターゲットの同じイベントに対して複数のイベントリスナーを登録
HTML の属性値や DOM で取得した要素のプロパティに対してイベントハンドラを登録した場合、属性値やプロパティは一つの値しか保管できないため、同じイベントに対するイベントハンドラは一つしか登録することができない。
しかし、 addEventListener メソッドを使ってイベントリスナーを登録する場合には、同じターゲットの同じイベントに対して複数のイベントリスナーを登録することができる。
ベントが発生すると登録されている順番に複数のイベントリスナーが呼び出される。
<input type="button" value="button" id="test" />
<script>
function dispGreeting() {
console.log("こんにちは");
}
function dispGoodNight() {
console.log("こんばんは");
}
let button = document.getElementById("test");
button.addEventListener("click", dispGreeting);
button.addEventListener("click", dispGoodNight);
</script>
イベントリスナーを解除
- removeEventListener メソッドは指定のイベントが発生したときに実行されるイベントリスナーを登録する
target.removeEventListener(type, callback [, options])
- 削除するイベントリスナーを登録したときと同じ引数を指定する
- 一致するイベントリスナーを削除
<input type="button" value="button" id="test" />
<script>
function buttonClick() {
console.log("こんにちは!これで最後です。");
this.removeEventListener("click", buttonClick);
}
let button = document.getElementById("test");
button.addEventListener("click", buttonClick);
</script>
一度だけイベントリスナーが呼びだされると、かんすないでイベントリスナーが解除される。
- 無名関数を利用している場合第二引数に実行しちる関数を参照することができる
arguments.callee
を指定する
発生したイベントの情報を取得する(Event)
イベントが発生して登録されたイベントハンドラやイベントリスナーが呼び出されると、一番目の引数に発生したイベントの情報が格納された Event オブジェクトが渡されてくる。
Eventオブジェクトの受け取り
ターゲットとなる要素のプロパティに対してイベントハンドラを登録する場合と、 addEventListener メソッドを使ってイベントリスナーを登録した場合、イベントが発生すると登録したコールバック関数が呼び出され、その時、第一引数に発生したイベントの情報が格納されたEventオブジェクトが渡される。
関数内でEventオブジェクトの情報を使いたい場合に活用できる。
<script>
function butotnClick(event){
console.log('こんにちは');
}
let button = document.getElementById('test');
button.addEventListener('click', butotnClick);
</script>
Eventオブジェクトで取得できる情報
コールバック関数が呼び出されるときに引数として渡されてきた Event オブジェクトのプロパティを参照することで、発生したイベントに関する情報を取得できる。
プロパティ名 |
説明 |
Event.eventPhase |
イベントのフェーズ(キャプチャリングフェーズ、ターゲットフェース、バブリングフェーズ) |
Event.type |
イベントの種類を表す文字列 |
Event.target |
イベントが発生した要素 |
Event.isTrusted |
イベントがユーザーの操作によって発生したかどうか |
Event.bubbles |
イベントがバブリングするかどうか |
Event.timeStamp |
要素が作成されてからイベント発生までの経過時間(ミリ秒) |
Event.cancelable |
イベントがキャンセル可能かどうか |
Event.currentTarget |
イベントハンドラを登録した要素 |
以下のように使う
event.type
使用例
<p>ボタンをクリックしてください。</p>
<input type="button" value="button" id="xxx" />
<script>
let button = document.getElementById("xxx");
button.addEventListener("click", function (event) {
console.log("bubbles :" + event.bubbles);
console.log("cancelable :" + event.cancelable);
console.log("currentTarget :" + event.currentTarget);
console.log("eventPhase :" + event.eventPhase);
console.log("target :" + event.target);
console.log("timeStamp :" + event.timeStamp);
console.log("type :" + event.type);
console.log("isTrusted :" + event.isTrusted);
});
</script>
Event.currentTargetプロパティとEvent.targetプロパティの違い
プロパティ名 |
説明 |
Event.currentTarget |
イベントハンドラを登録した要素 |
Event.target |
イベントが発生した要素 |
Event.curentTarget
は以下のようなイベントハンドラを登録したターゲットの要素を指す。
let button = document.getElementById('xxx');
button.addEventListener('click', butotnClick);
Event.target
は実際にイベントが発生した要素を指します。
イベントに対するデフォルトの動作をキャンセルする(preventDefault)
リンクをクリックすれば、リンク先のページに移動したり、チェックボックスをクリックすればチェックが入るなどのデフォルトの動きが設定されているがpreventDefault
を使用するとキャンセルすることができる。
event.preventDefault()
- すべてのイベントでキャンセルが可能ではない
Event.cancelable
プロパティの値が true のイベントのみキャンセル可能
<body>
<div>
<input type="checkbox" id="check1" />
<label for="check1">はい</label>
<input type="checkbox" id="check2" />
<label for="check2">いいえ</label>
</div>
<script>
let checkBox = document.getElementById("check2");
checkBox.addEventListener("click", function (event) {
alert("現在変更できません");
event.preventDefault();
});
</script>
</body>
「はい」にはチェックがいれられるが、「いいえ」をクリックするとアラートが出現してチェックが入らなくなる。
イベントをコードから発生させる(dispatchEvent)
イベントは HTTP ページをブラウザで見ているユーザーの操作によって発生するが、プログラムの中で新しいイベントを作成し指定した対象でイベントを発生させることがでできる。
- 作成するには Event オブジェクトをのコンストラクタを使用
new Event(eventtype[, option])
- 第一引数にイベントの種類を表す文字列を指定
- カスタムイベントを作る場合は任意の名前
- 第二引数には以下の3つの値に関する値をもったオブジェクトを指定する(省略可能)
- bubbles(初期値は false):
バブリングフェーズでイベントが伝搬されていくかどうか
- cancelable(初期値は false):
イベントがキャンセル可能かどうか
- composed(初期値は false)
- click イベントを新しく作成するには次のように記述
let e = Event('click');
イベントを発生させる
- dispatchEvent メソッドは対象となるターゲットに引数に指定したイベントを発生させる
- 引数には Event オブジェクトを指定
target.dispatchEvent(event)
- click イベントを発生させるには次のように記述
let e = Event('click');
let target = document.getElementById('test');
target.dispatchEvent(e);
- 発生したイベントがユーザーの操作によって発生したものか、それとも dispatchEvent メソッドによるコードから発生させられたものかは
Event.isTrusted
プロパティを参照することで判別できる
<body>
<div>
<input type="button" id="btn1" value="button1" />
<input type="button" id="btn2" value="button2" />
</div>
<script>
let btn1 = document.getElementById("btn1");
let btn2 = document.getElementById("btn2");
btn1.addEventListener("click", function (event) {
console.log("buttonA:" + event.isTrusted);
let newEvent = new Event("click");
btn2.dispatchEvent(newEvent);
});
btn2.addEventListener("click", function (event) {
console.log("buttonB:" + event.isTrusted);
});
</script>
</body>
- ボタン1が押された場合
まずユーザーのクリックにより表示されるので
buttonA:true
が表示され、そのあとにクリックイベントを作成し、 dispatchEvent メソッドによってボタン2もユーザーの行動によらず押される。そのためボタンBのisTrusted
ではfalseとなっている。