Newer
Older
hello-programmer-world / src / pages / js / 050-js-with-html.mdx
---
layout: "@/layouts/MarkdownLayout.astro"
---

import RenderFile from "@/components/RenderFile";
import RenderHtml from "@/components/RenderHtml";

export const title = "ボタンをクリックしたら処理する";

# {title}

## TOC

## とりあえず見てみよう

```html file=public/sample/js/button.html
public/sample/js/button.html
内容を取得できませんでした
```

<RenderFile path="public/sample/js/button.html" />

`クリック!`ボタンがありますね、これをクリックしてみましょう。  
`ボタンがクリックされました!`とメッセージが表示されたと思います。

<br />

動作がわかったところで、ソースコードを見ていきましょう。

<br />

以下の箇所は`<button>`タグですね。これがボタンとして表示されています。  
これがクリックされたときに、先ほどのメッセージが表示されていました。

```html file=public/sample/js/button.html {1}
public/sample/js/button.html
内容を取得できませんでした
```

<br />
<br />

この下に、`<script>`タグがありますね。  
この中に書かれているものが、`JavaScript`です。

```html file=public/sample/js/button.html {3-8}
public/sample/js/button.html
内容を取得できませんでした
```

<br />
<br />

最初の行には、`const button = document.querySelector("button");`とありますね。  
今のこれが何なのかよくわからないかもしれませんが、どうやら上に書いてあったボタンを取得しているようですね。  
そのボタンが、`button`という変数に入れられています。

```html file=public/sample/js/button.html {4} '<button type="button">クリック!</button>'
public/sample/js/button.html
内容を取得できませんでした
```

<br />
<br />

その次を見てみると、`button`から`addEventListener`が伸びていますね。  
その直後に、メッセージの文章になっていた`ボタンがクリックされました!`という記述があります。

```html file=public/sample/js/button.html {5-7}
public/sample/js/button.html
内容を取得できませんでした
```

<br />

## 解説

### document.querySelector()

例として以下のHTMLを提示していました。  
そこでは、`button`という変数を新たに作成し、`document.querySelector("button")`の結果を代入していました。

```html file=public/sample/js/button.html {4} "document"
public/sample/js/button.html
内容を取得できませんでした
```

この記述の動作を日本語で説明すると、  
**ブラウザで表示中のHTMLの中から`button`タグを探して、その最初の要素を取得しなさい。**  
となります。  

`document`は**ブラウザで表示中のHTML全体**を管理している、ブラウザが提供している特別なオブジェクトです。  
その中の`querySelector`という機能を使うことで、HTMLの中から特定の要素を探し出し、JavaScriptからその要素を操作できるようにしています。

<br />
<br />

ところで、`querySelector`の名前にもなっているセレクターとは何でしょうか?  
同じ呼ばれ方をしているものが、[HTMLを装飾するCSS](../html/02-css) でも登場していました。

実は、CSSで使われているセレクターと、JavaScriptで使われているセレクターは同じものです。

今回の例では`document.querySelector("button")`と書かれていました。  
この括弧の中に書かれている`button`こそが、HTMLの`<button>`タグを指し示すセレクターです。

CSSと同様に、class属性やid属性を使って要素を指定することもできます。

```html
<button>クリック!</button>
<script>
  const button = document.querySelector("button");
</script>
```

<br />

```html
<button class="btn">クリック!</button>
<script>
  const button = document.querySelector(".btn");
</script>
```

<br />

```html
<button id="special-button">クリック!</button>
<script>
  const button = document.querySelector("#special-button");
</script>
```

### addEventListener()

以下のソースコードは、ボタンをクリックしたときにメッセージを表示するという例でした。  
このクリックしたときの動作を実現していたのが、`addEventListener`という機能です。

```html file=public/sample/js/button.html {5-7}
public/sample/js/button.html
内容を取得できませんでした
```

先に第2引数を見てみましょう。  
そこには実際に表示されていたメッセージ、`ボタンがクリックされました!`が書かれていましたね。  
どうやらそこに、クリックされたときの動作が書かれているようです。

注意して欲しいのは、第2引数に渡しているものは、**関数そのもの**であるということです。

```js
const button = document.querySelector("button");

function handleClick() {
  alert("ボタンがクリックされました!");
}

// handleClickという関数そのものを第2引数に渡している
// handleClick() として実行してはいない
button.addEventListener("click", handleClick);
```

<br />

そして第1引数を見てみましょう。

第1引数は、**どんなときに第2引数の動作(=イベント)を実行するのかを決めるためのもの**です。

第2引数は、**クリックされたときの動作**を定義しているものでした。  
このクリックしたときの動作(=clickイベント)を表す`"click"`が、今回第1引数に指定されているというわけです。

イベントには様々な種類があります。  
こんなものがあるんだな程度でいくつか把握しておくと良いでしょう。

[【javascript】addEventListenerイベントまとめ](https://qiita.com/whw3312/items/94a2bdf632ef77555579)

## 応用

### document.querySelectorAll()

ボタンに限った話ではありませんが、HTMLの中に同じような要素が複数ある場合があります。

`document.querySelector`は最初に見つかった1つの要素しか取得できませんでした。  
それでは2番目、3番目の要素を取得したい場合はどうすれば良いでしょうか?

その答えの1つに、`document.querySelectorAll`を使う方法があります。

`document.querySelectorAll`は、指定したセレクターに一致する**すべての要素**を取得できます。  
これを`for`文などと組み合わせることで、複数の要素に対して同じ処理を実行することができます。

以下の例は複数の`<button>`タグに対して、その全てにクリックイベントを設定しています。

```html file=public/sample/js/querySelectorAll.html
public/sample/js/querySelectorAll.html
内容を取得できませんでした
```

<RenderFile path="public/sample/js/querySelectorAll.html" />

### 複数のイベントを登録する

`addEventListener`は1つの要素に対して、複数のイベントを設定することもできます。

```html file=public/sample/js/multiple-events.html
public/sample/js/multiple-events.html
内容を取得できませんでした
```

<RenderFile path="public/sample/js/multiple-events.html" />