## 事象
以下のような`CountUpButton`コンポーネントを作成しても、[[v-model]]が期待通り動かない。このコードはもともと[[Vue2]]で動作していたものをそのまま使おうとしている。
`main.vue`
```html
<script setup lang="ts">
import { ref } from "vue";
import CountUpButton from "./components/CountUpButton.vue";
const count = ref(0);
</script>
<template>
<CountUpButton v-model="count" />
</template>
```
`CountUpButton.vue`
```html
<script setup lang="ts">
const props = defineProps<{
value: number;
}>();
const emit = defineEmits<{
input: [value: number];
}>();
const handleClick = () => {
emit("input", props.value + 1);
};
</script>
<template>
<button @click="handleClick">Count up {{ value }}</button>
</template>
```
以下のように途中が省略された長い型エラーが出る。
```error
Argument of type '{ modelValue: number; }' is not assignable to parameter of type 'Partial<{}> & Omit<{ readonly value: number; onUpdate?: ((value: number) => any) | undefined; } & VNodeProps & AllowedComponentProps & ComponentCustomProps & Readonly<...> & { ...; }, never> & Record<...>'.
Property 'value' is missing in type '{ modelValue: number; }' but required in type 'Omit<{ readonly value: number; onUpdate?: ((value: number) => any) | undefined; } & VNodeProps & AllowedComponentProps & ComponentCustomProps & Readonly<...> & { ...; }, never>'.
```
## 原因
[[Vue3のv-modelに対する破壊的に変更]]に対応していないから。
[[Vue3ではv-model相当のpropにmodelValue(model-value)を使う]]ので、`value`のpropは認識されない。また、`input`も`update:???`でなくてはいけない。
## 解決方法
インターフェースを変える場合と変えない場合で2通りの方法がある。
### インターフェースを変える方法
`v-model`を`v-model:value`に変えることで、コンポーネントのpropは変更しなくて済む。
```html
<template>
<CountUpButton v-model:value="count" />
</template>
```
ただし、eventは変更が必要。`input`は`update:value`にしなければならない。
`CountUpButton.vue`
```html
<script setup lang="ts">
const props = defineProps<{
value: number;
}>();
const emit = defineEmits<{
"update:value": [value: number];
}>();
const handleClick = () => {
emit("update:value", props.value + 1);
};
</script>
<template>
<button @click="handleClick">Count up {{ value }}</button>
</template>
```
いずれにせよ変更が必要なら、このあとの[[#インターフェースを変えない方法]]の方がいい気がする。
### インターフェースを変えない方法
propsの`value`を`modelValue`に変更し、`inpute`を`update:modelValue`に変更する。ライブラリとしてコンポーネントを提供する場合はこの方が親切である。
`CountUpButton.vue`
```html
<script setup lang="ts">
const props = defineProps<{
modelValue: number;
}>();
const emit = defineEmits<{
"update:modelValue": [value: number];
}>();
const handleClick = () => {
emit("update:modelValue", props.modelValue + 1);
};
</script>
<template>
<button @click="handleClick">Count up {{ modelValue }}</button>
</template>
```
```html
<template>
<CountUpButton v-model="count" />
</template>
```