LoginSignup
26
16

More than 3 years have passed since last update.

【Vue 3 入門】双方向データバインディングの標準化

Last updated at Posted at 2021-02-01

はじめに

Vue 2 のリリースから Vue 3 の開発に至るまで、双方向データバインディングのより柔軟な利用を実現するため、様々な取り組みが行われてきました。本稿では Vue 3 のリリースに伴い v-model双方向データバインディングの標準化 に向けて、どのような破壊的変更がされたかについて解説します。

‎TL;DR

  • コンポーネント利用時の propevent のデフォルト名の変更
  • .sync 修飾子の廃止、代替構文の追加
  • 同一コンポーネントで複数の v-model の利用可
  • カスタム修飾子の作成可

コンポーネント利用時の propevent のデフォルト名の変更

v-model はユーザーの入力イベントにおいてデータを更新するための糖衣構文です。Vue 2 のコンポーネントで v-model を利用した場合、以下のような糖衣構文になります。詳しい内容は『【Vue.js 再入門】 v-model を正しく理解して親子間コンポーネントのデータ伝播をマスターする』を参照ください。

<MyComponent
  :value="message"
  @input="message = $event"
/>

Vue 3 のリリースに伴い、コンポーネント利用時の propevent のデフォルト名が変更になりました。こちらは HTML 属性の名前の衝突を避けるために変更されました。

  • prop:value → modelValue
  • event:input → update:modelValue

.sync 修飾子の廃止、双方向データバインディングの標準化

.sync 修飾子は v-model と同様に props の値に対して双方向データバインディングを実現できます。主な違いは .sync 修飾子を利用すれば、同一コンポーネントに複数の双方向データバインディングを実現できることです。

<MyComponent
  :first-name.sync="firstName"
  :last-name.sync="lastName"
/>

しかし .sync 修飾子の存在は双方向データバインディングを実現する上で 混乱を招く要因 になります。ゆえに Vue 3 では .sync 修飾子を廃止し、v-model をより柔軟に利用できるよう、双方向データバインディングを標準化しました。そこで v-model には新機能の「 v-model の引数」と「同一コンポーネントに対する v-model の複数可」が追加されました。

v-model の引数

v-model の引数は .sync 修飾子の廃止に伴い追加された v-model の新しい構文です。下図のように v-model に引数を渡せるようになり、.sync 修飾子と同等の機能を有します。ここで v-model というのは v-model:model-value の省略形であることが理解できます。ちなみに、本機能の追加によりコンポーネントの model オプションが不要になり Vue 3 で削除されました。

同一コンポーネントに対する v-model の複数可

Vue 3 では同一コンポーネントに複数の v-model を利用可能になりました。.sync 修飾子に代わる v-model の新機能です。

<UserName
  v-model:first-name="firstName"
  v-model:last-name="lastName"
/>

ちなみに上記のコード例の糖衣構文は以下のようになります。

<UserName
  :first-name="firstName"
  @update:firstName="firstName = $event"
  :last-name="lastName"
  @update:lastName="lastName = $event"
/>

カスタム修飾子の作成可

Vue 3 は v-model に独自のカスタム修飾子を追加できるようになりました。実際に「先頭の文字を大文字にする」機能を有する .capitalize カスタム修飾子の実装例で説明します。

<MyComponent v-model.capitalize="myText" />

独自のカスタム修飾子があるコンポーネントは props 経由で modelModifiers にオブジェクト形式で含まれます。本例の modelModifiers には { capitalize: true } が格納されています。デフォルトの場合 modelModifiers という名前になりますが、v-model に引数を渡す場合は arg + Modifiers という命名規則になります。

<template>
  <input type="text" @input="handleInput" />
</template>

<script>
export default {
  props: ['modelModifiers'],
  emits: ['update:modelValue'],
  setup(props, { emit }) {
    const handleInput = (event) => {
      let value = event.target.value
      if (props.modelModifiers.capitalize) {
        value = value.charAt(0).toUpperCase() + value.slice(1)
      }
      emit('update:modelValue', value)
    }
    return {
      handleInput,
    }
  },
}
</script>

:warning: setup 関数の第 1 引数の props を分割代入しないように注意しましょう。props 経由のデータのリアクティブが失われます。

さいごに

ここまで双方向データバインディングの標準化に向けた v-model の新機能や、破壊的変更について取り上げました。本稿が読者の理解の一助になれば幸甚です。

参考文献

26
16
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
26
16