ymmooot

Vue の template でカリー化関数に部分適用する

以下のようなコンポーネントがあるとする。

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>

@changev-on:change の省略記法だが、v-on はオブジェクトを受け取れ、キーがイベント名、値がイベントハンドラとなる。
これが唯一 template のイベントハンドラ宣言時に JavaScript を実行できる記法である。
以上。