以下のようなコンポーネントがあるとする。
Comp.vue<template>
<input v-model="val">
</template>
<script setup lang="ts">
const val = ref('');
const emit = defineEmits<{
change: [str: string, num: number]
}>();
watch(val, str => {
const num = Math.floor(Math.random() * 11);
emit('change', str, num);
});
</script>
これを親から呼び出す。
Parent.vue<template>
<div v-for="v in 3" :key="v">
<Comp @change="onChange(v)" />
</div>
</template>
<script setup lang="ts">
const onChange = v => (str, num) => {
console.log(v, str, num);
};
</script>
これでは console.log(v, str, num)
は呼ばれない。Vue は @change="onChange(v)"
と記述すると、 onChange(v)
を change イベントの度に実行するため、template の宣言時に部分適用できない。
これは以下のように書くと実現できる。
Parent.vue<template>
<div v-for="v in 3" :key="v">
<Comp v-on="{ change: onChange(v) }" />
</div>
</template>
@change
は v-on:change
の省略記法だが、v-on はオブジェクトを受け取れ、キーがイベント名、値がイベントハンドラとなる。
これが唯一 template のイベントハンドラ宣言時に JavaScript を実行できる記法である。
以上。