19
8

【Vue3】バージョン3.4から安定版となった「defineModel」が超便利

Last updated at Posted at 2024-03-09

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に更新後の値を渡して実行するような形で記述していました。

記述が複雑で、何をやっているのかも分かりにくく、個人的にあまり好きではないコードでした。

子コンポーネント(TextInput.vue)
<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>

または

子コンポーネント(TextInput.vue)
<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に作成した変数を指定するだけで、完成です!

かなりシンプルになりますね。

子コンポーネント(TextInput.vue)
<template>
  <input type="text" v-model="model" />
</template>

<script setup>
const model = defineModel();
</script>

複数のv-modelを指定

defineModelには、引数を渡すことができます。第一引数として渡された文字列は、モデル名として使用されます。

親コンポーネントで使用する際にv-model:モデル名のように指定することで、紐付けるモデルを指定することができます。これを利用することで複数のv-modelを扱うことができるので、とても便利です。

指定するモデル名は重複してはいけないという点に注意してください。

子コンポーネント(TextInput.vue)
<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>
19
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
19
8