Skip to content
sumnail

Vue3のイベント修飾子

created at : 2024/08/16

Vue3

イベント修飾子とは

Vue では、イベント修飾子を使用してイベント発生時の挙動を制御することができます。

イベント修飾子は、v-on:clickまたは@clickの後などにドット(.)を付けて記述します。

イベント修飾子の一覧

.stop

.stop 修飾子は、イベントの伝播を停止します。

サンプル

[]
[]
サンプルコード
vue
<template>
  <div @click="handleClick">
    <button @click="handleClick">without stop</button>
  </div>
  {{ arr }}
  <div @click="handleClickStop">
    <button @click.stop="handleClickStop">with stop</button>
  </div>
  {{ arrWithStop }}
</template>

<script setup>
import { ref } from "vue";

const arr = ref([]);
const arrWithStop = ref([]);

const handleClick = () => {
  arr.value.push("click");
};

const handleClickStop = () => {
  arrWithStop.value.push("click");
};
</script>

<style scoped>
button {
  margin: 10px;
  padding: 10px;
  color: var(--text-color);
  background-color: var(--secondary-color);
  border: none;
  border-radius: 4px;
}
</style>

stop 修飾子なしは、ボタンのクリックイベント後に親要素のクリックイベントは発生し、一度のクリックでclickが 2 回追加されます。

stop 修飾子ありは、ボタンのクリックイベントが親要素へ伝播されるのを防ぎ、親要素のクリックイベントは発生しません。

.prevent

.prevent 修飾子は、デフォルトのイベントをキャンセルします。

サンプル

submitted : false
サンプルコード
vue
<template>
  <form @submit="handleSubmit">
    <button type="submit">without prevent</button>
  </form>
  <form @submit.prevent="handleSubmit">
    <button type="submit">with prevent</button>
  </form>
  <div>submitted : {{ submitted }}</div>
</template>

<script setup>
import { ref } from "vue";

const submitted = ref(false);

const handleSubmit = () => {
  submitted.value = true;
  console.log("submitted");
};
</script>

<style scoped>
button {
  margin: 10px;
  padding: 10px;
  color: var(--text-color);
  background-color: var(--secondary-color);
  border: none;
  border-radius: 4px;
}
</style>

prevent 修飾子なしは、フォームの送信イベントによりページがリロードされます。 prevent 修飾子ありをクリックすると、フォームの送信イベントによるページがリロードされるのを防ぎます。

.capture

.capture 修飾子は、イベントをキャプチャーモードで処理します。

サンプル

[]
[]
サンプルコード
vue
<template>
  <div>
    <button @click="handleClick(1)">
      <button @click="handleClick(2)">
        <button @click="handleClick(3)">without capture</button>
      </button>
    </button>
    <div class="result">
      {{ arr }}
    </div>
  </div>
  <div>
    <button @click.capture="handleClickCapture(1)">
      <button @click.capture="handleClickCapture(2)">
        <button @click.capture="handleClickCapture(3)">with capture</button>
      </button>
    </button>
    <div class="result">
      {{ arrWithCapture }}
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";

const arr = ref([]);
const arrWithCapture = ref([]);

const handleClick = (value) => {
  arr.value.push(value);
};

const handleClickCapture = (value) => {
  arrWithCapture.value.push(value);
};
</script>
<style scoped>
button {
  padding: 4px;
  color: var(--text-color);
  background-color: var(--secondary-color);
  border: none;
  border-radius: 4px;
}

.result {
  margin: 10px 0;
}
</style>

capture 修飾子なしは、子要素のクリックイベントが先に発生し、親要素のクリックイベントが後に発生します。

capture 修飾子ありは、親要素のクリックイベントが先に発生し、子要素のクリックイベントが後に発生します。

.self

.self 修飾子は、自身の要素でのみイベントを処理します。

サンプル

Is Clicked? : No...
Is Clicked? : No...
サンプルコード
vue
<template>
  <div>
    <button @click="handleClick" class="btn">
      <div class="div-btn">without self</div>
    </button>
  </div>
  <div class="result">Is Clicked? : {{ msg }}</div>
  <div>
    <button @click.self="handleClickWithSelf" class="btn">
      <div class="div-btn">with self</div>
    </button>
  </div>
  <div class="result">Is Clicked? : {{ msgWithSelf }}</div>
</template>

<script setup>
import { ref } from "vue";

const msg = ref("No...");
const msgWithSelf = ref("No...");

const handleClick = () => {
  msg.value = "clicked";
};

const handleClickWithSelf = () => {
  msgWithSelf.value = "clicked";
};
</script>

<style scoped>
.div-btn {
  padding: 4px;
  background-color: var(--secondary-color);
  border-radius: 4px;
}

.btn {
  padding: 16px;
  color: var(--text-color);
  background-color: var(--main-color);
  border: none;
  border-radius: 4px;
}

.result {
  margin: 8px 0;
}
</style>

self 修飾子なしは、子要素のクリックでもイベント処理が行われます。

self 修飾子ありは、自身の要素でのみクリックイベントが処理されます。

.once

.once 修飾子は、イベントリスナーを一度だけ実行します。

サンプル

Count : 0

Count : 0

サンプルコード
vue
<template>
  <button @click="handleClick">without once</button>
  <p>Count : {{ count }}</p>
  <button @click.once="handleClickWithOnce">with once</button>
  <p>Count : {{ countWithOnce }}</p>
</template>

<script setup>
import { ref } from "vue";

const count = ref(0);
const countWithOnce = ref(0);

const handleClick = () => {
  count.value++;
};

const handleClickWithOnce = () => {
  countWithOnce.value++;
};
</script>

<style scoped>
button {
  padding: 8px 16px;
  color: var(--text-color);
  background-color: var(--main-color);
  border: none;
  border-radius: 4px;
}
</style>

once 修飾子なしは、クリックするたびにカウンターが増加します。

once 修飾子ありは、クリックしても一度だけカウンターが増加します。

.passive

.passive 修飾子は、スクロールイベントやタッチイベントにおけるパフォーマンスの劣化を防ぎます。

使用例

デフォルト動作がキャンセル(preventDefault)されないことを宣言しておくことで、スクロール動作をイベントリスナーの処理を待たず実行できるため、パフォーマンス劣化を防ぎます。

サンプルコード
vue
<template>
  <div class="window" @scroll.passive="handleScrollWithPassive">
    with passive
  </div>
</template>

<script setup>
const handleScrollWithPassive = () => {
  console.log("scrolling...");
};
</script>

まとめ

イベント修飾子を使用してイベント発生時の挙動を効率良く制御できます。

参考