2023年12月28日、Vue.jsの最新バージョン「3.4」がリリースされました。
今回のアップデートで安定版となったdefineModel
が超便利なので、紹介したいと思います。
用途
コンポーネントを使用する際、v-model
に親コンポーネントで定義したデータ(ref
/ reactive
)を指定する際に使用します。
たとえば以下のように、テキストフォームのコンポーネントを作成して、親コンポーネントで定義したref(username
)をそのままv-model
に指定するような状況ですな。
<template>
<div>
<TextInput v-model="username" />
</div>
</template>
<script setup>
import { ref } from "vue";
import TextInput from "./TextInput.vue";
const username = ref("");
</script>
バージョン3.3までの記述
バージョン3.3までは、propsとしてmodelValue
を受け取り、更新する際にはemitのupdate:modelValue
に更新後の値を渡して実行するような形で記述していました。
記述が複雑で、何をやっているのかも分かりにくく、個人的にあまり好きではないコードでした。
<template>
<input type="text" v-model="model" />
</template>
<script setup>
import { defineProps, defineEmits, computed } from "vue";
const props = defineProps(["modelValue"]);
const emit = defineEmits(["update:modelValue"]);
const model = computed({
get: () => props.modelValue,
set: (inputted) => emit("update:modelValue", inputted)
});
</script>
または
<template>
<input
:value="props.modelValue"
@input="emit('update:modelValue', $event.target.value)"
/>
</template>
<script setup>
import { defineProps, defineEmits } from "vue";
const props = defineProps(["modelValue"]);
const emit = defineEmits(["update:modelValue"]);
</script>
バージョン3.4からの記述 / defineModel
を使用した記述
defineModel
を使用した場合、恐ろしくシンプルになります。
コンポーネントで、defineModel
メソッドを実行し、何かしらの変数(username
)に格納します。あとは、フォームのv-model
に作成した変数を指定するだけで、完成です!
かなりシンプルになりますね。
<template>
<input type="text" v-model="model" />
</template>
<script setup>
const model = defineModel();
</script>
複数のv-model
を指定
defineModel
には、引数を渡すことができます。第一引数として渡された文字列は、モデル名として使用されます。
親コンポーネントで使用する際にv-model:モデル名
のように指定することで、紐付けるモデルを指定することができます。これを利用することで複数のv-model
を扱うことができるので、とても便利です。
指定するモデル名は重複してはいけないという点に注意してください。
<template>
<input type="text" v-model="username" />
<input type="number" v-model="age" />
</template>
<script setup>
const username = defineModel("username");
const age = defineModel("age");
</script>
<template>
<div>
<TextInput v-model:username="username" v-model:age="age" />
</div>
</template>
<script setup>
import { ref } from "vue";
import TextInput from "./TextInput.vue";
const username = ref("");
const age = ref(0);
</script>