採点されません。匿名です。 間違えることは学習の一部です。読むだけでもかまいません。

Vue — v-on / @ (イベント)

テクノロジ系 / L01 template-syntax — テンプレート構文

Vue — v-on / @ (イベント)

基本

<script setup>
const count = ref(0);
function increment() { count.value++; }
</script>

<template>
  <button @click="increment">+</button>
  <button @click="count++">+</button>            <!-- インライン -->
  <button @click="count = count - 1">-</button>
  <button @click="handle($event, count)">handle</button>  <!-- 引数渡し -->
</template>

@event で各種イベント。

ref / count.value は L03 ch01。

イベント Modifier

<template>
  <!-- .prevent: event.preventDefault() -->
  <form @submit.prevent="onSubmit">...</form>

  <!-- .stop: event.stopPropagation() -->
  <div @click="outer"><button @click.stop="inner">Btn</button></div>

  <!-- .once: 1回だけ -->
  <button @click.once="init">Initialize</button>

  <!-- .self: 自分自身で発火したときだけ -->
  <div @click.self="closeModal">背景</div>
</template>

JS で e.preventDefault() を書く代わりに .prevent で済む。

Key Modifier

<template>
  <input
    @keydown.enter="submit"
    @keydown.esc="cancel"
    @keydown.ctrl.s="save"
  />
</template>

主要キー: enter, tab, delete, esc, space, up, down, left, right

修飾: .ctrl, .alt, .shift, .meta, .exact

@keydown.ctrl.s で「Ctrl+S」を捕捉。

Mouse Modifier

<template>
  <button @click.left="leftClick">Left</button>
  <button @click.right="rightClick">Right</button>
  <button @click.middle="middleClick">Middle</button>
</template>

ハンドラに引数

<template>
  <button v-for="item in items" :key="item.id"
    @click="deleteItem(item.id)">
    Delete
  </button>
</template>

呼び出し式 deleteItem(item.id) の形で書ける。

イベントオブジェクトと両方欲しいなら:

<button @click="handleClick($event, item.id)">Delete</button>

$event で event object。

TypeScript で型付け

<script setup lang="ts">
function handleInput(e: Event) {
  const target = e.target as HTMLInputElement;
  console.log(target.value);
}
</script>

<template>
  <input @input="handleInput" />
</template>

inline で書くなら ($event as any) か as キャストが必要。

ハンドラ関数に切り出す方が型がきれい。

まとめ

  • @event="..." でイベント (v-on: の短縮)
  • modifier で preventDefault / stopPropagation / once 等が書ける
  • key modifier で Enter / Esc / Ctrl+S 等を捕捉
  • 引数あり呼び出しも書ける
  • $event で event object 参照
  • TS では関数に切り出して型を付ける

次は v-if / v-show

考えてみよう

既定では正解・不正解の判定はしません。自分のペースで「答えを見る」を。採点してほしい場合だけ「採点してほしい」を押してください。

Lv1: 基本 — イベントハンドラ

問題

<script setup>
const count = ref(0);
const text = ref("");

function increment() { count.value++; }
function reset() { count.value = 0; }
function handle(e: KeyboardEvent) {
  console.log(e.key);
}
</script>

<template>
  <p>{{ count }}</p>
  <button @click="increment">+</button>
  <button @click="count++">+ inline</button>
  <button @click="reset">reset</button>
  <input v-model="text" @keydown="handle" />
</template>

合格基準

  • 4イベント全部動く
  • インライン式と関数の両方OK

Lv2: 応用 — Modifier

問題

<template>
  <form @submit.prevent="onSubmit">
    <input @keydown.enter="onEnter" />
    <input @keydown.ctrl.s="onSave" />
    <input @keydown.esc="onCancel" />
    <button>Submit</button>
  </form>

  <div @click="outer">
    <button @click.stop="inner">inner (stopPropagation)</button>
  </div>

  <button @click.once="initOnce">Init (1回だけ)</button>
</template>

各 modifier の効果を観察。

合格基準

  • .prevent でリロード止まる
  • .stop で親の click 走らない
  • .once で1回しか発火しない
  • .enter / .ctrl.s / .esc が動く

Lv3: 発展 — TS で型付き event handler

問題

<script setup lang="ts">
function handleInput(e: Event) {
  const target = e.target as HTMLInputElement;
  console.log(target.value);
}

function handleSubmit(e: SubmitEvent) {
  e.preventDefault();
  const form = e.target as HTMLFormElement;
  const data = new FormData(form);
  console.log(Object.fromEntries(data));
}
</script>

<template>
  <form @submit="handleSubmit">
    <input name="name" @input="handleInput" />
    <button>Submit</button>
  </form>
</template>

合格基準

  • TS で event 引数に型
  • form data 取得

提出

submission.md に3問の回答を。