v-onディレクティブでのイベントオブジェクトの扱い、修飾子について

## この記事の目的
* v-onディレクティブの基本的な使い方を学ぶ。
* 修飾子の使い方を学ぶ。



## v-onディレクティブとイベントオブジェクト
業務中でv-onディレクティブの使い所、また修飾子について疑問に思うところがあったので基本的なところをまとめます。
まずv-onディレクティブはv-bindとは違って、属性ではなくイベントの種類を引数にとります。（ここで引数とはv-on:のあとに続くものです。）
実際にテスト画面を見てみましょう。

![スクリーンショット 2023-10-29 16.54.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/56d3e8d1-9f17-5c96-1dd5-d4cd9f506c3c.png)

![スクリーンショット 2023-10-29 16.54.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/4f7371bc-2179-0d67-71e0-da8992509a59.png)
画像の通り、イベント発火前には『イベント前(Click me!)」という文言、背景色が黄色になっています。一方この黄色い部分をクリックすると、赤く変わり表示の値が「11963.8...」と変わっていますね。これはpタグをクリックしたことでonPClickWithEventメソッドが呼ばれ、同時に引数であるredという文字列, イベントオブジェクトである$eventが渡されているのです。これによりstyle属性がyellowからredに変わり、背景色が変化します。
コードは以下です。

```html
  <p v-on:click="onPClickWithEvent('red', $event)" v-bind:style= "{backgroudColor:
  pBgColorEvent}">
    {{ pMsg }}
  </p>
```
```ts
import { ref } from "vue";
const pMsg = ref("イベント前(Click me!))")
const pBgColorEvent = ref('yellow');
const onPClickWithEvent = (bgColor: string, event: MouseEvent): void => {
  PBgColorEvent.value = bgColor;
  pMsg.value = event.timeStamp.toString();
};
```
テンプレートタグの中から見ていきます。今回はイベントハンドラに二つの引数を渡しています。背景色を示す文字列のred、それからイベントオブジェクトを示す$eventです。<br>
またv-bindディレクティブではstyle属性をバインディングしています。背景色としてpBgColorEventというスクリプトタグで定義したテンプレート変数を利用しています。
つぎにスクリプトタグを見ていきます。スクリプトタグでは、いくつかテンプレート変数が定義してあるほか、onPClickWithEventというメソッドが定義してあります。ここではPBgColorEventのvalueプロパティとして受け取ったbgColorを設定し、pMsgの値としてtimestampを文字列型にした値が定義されています。<br>

## 修飾子について（.stop）
つぎに.stopなどといった修飾子について取り上げます。修飾子はディレクティブの引数のあとに続けて書きます。修飾子には.stop, .capture, .preventなどがあります。
```html
<div class="parent" @click="parentMethod">
  <button class="child" @click.stop="childMethod">Click me</button>
</div>
<div class="msg">{{ msg }}</div>
```
```ts
import {ref} from "vue";

const msg = ref("未送信");
const parentMethod = (): void => {
  msg.value = "親要素"
}
const childMethod = (): void => {
  msg.value = "子要素"
}

```
ここで注目してもらいたいのは、v-onディレクティブ（今回は省略形@で表す）が二つ設定されているところです。
バブリングフェーズで子要素から親要素へイベントが伝播するのを「.stop」修飾子が防いでくれているのです。(バブリングについては外部サイトを参考にしていただけると幸いです。https://ja.javascript.info/bubbling-and-capturing)
![スクリーンショット 2023-10-30 6.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/a2e91414-d8fd-b4bc-e0e1-27df4dab881c.png)

![スクリーンショット 2023-10-30 6.42.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/09639ad4-7191-1e18-d7dc-306c09db6ead.png)

![スクリーンショット 2023-10-30 6.43.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/2b27a678-8416-31df-9c60-b40f8805cd31.png)
## 修飾子について（.prevent)
次に.prevent修飾子を取り上げます。テスト画面から見てみましょう。

![スクリーンショット 2023-11-01 17.48.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/dcd220a2-fa7e-fda9-94fa-f9ce3aa58c0b.png)

![スクリーンショット 2023-11-01 17.48.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1051165/74ce55e0-2ab3-9c28-873e-efefc6cc83c2.png)

```html
<div id="app">
    <div class="form_wrapper">
        <form v-on:submit="sendDeleteNumber">
            <input class="form-text" type="text" v-model="textNonPrevent">
            <br>
            <input class="form-button" type="submit" value="submitで送信">
        </form>
    </div>
    <div class="form_wrapper">
        <form v-on:submit.prevent="sendKeepNumber">
            <input class="form-text" type="text" v-model="textPrevent">
            <br>
            <input class="form-button" type="submit" value="submit.preventで送信">
        </form>
    </div>
</div>
```
```ts
import { ref } from "vue";
const textPrevent = ref('');
const textNonPrevent = ref('');
const sendKeepNumber = () => {
      alert(`「${textPrevent.value}」をどこかに送信！formはそのまま残ります`)
}
const sendDeleteNumber = () => {
      alert(`「${textNonPrevent.value}」をどこかに送信！ついでに画面更新します`)
}

```
2個目のformタグ内でsubmitに.preventがついていることがわかると思います。
.preventはv-onを修飾してevent.preventDefault()を呼び出します。このメソッドはjsで用意されてあるメソッドです。役割は名前のとおりsubmitイベントの発生元であるフォームの、デフォルトの動きをキャンセルしてくれます。
「デフォルトの動き」とはフォーム内容を指定URLへ送信すること（指定がない時は現在のURL）です。なので.preventを書くことでここでは現在のURLへ送信することを防いでくれます。ページ上では.preventを書かないことでリロード作業が防がれ、フォームの内容が残ります。時間がある方は、.preventがない時と比較してみてください。.preventがないとリロードされないはずです。不必要なリロードを防ぐのに.preventを使っているということが言えます。

今回はイベントオブジェクトと二つの修飾子について紹介しました。ぜひ実際に試してみてください！


参考　
Vue3 フロントエンド開発の教科書　齋藤新三著
ROXX 開発者ブログ https://techblog.roxx.co.jp/entry/2019/02/08/122914