v-model
破壊的変更
概要
変更点の概要は次のとおりです:
- 破壊的変更: カスタムコンポーネントで使用する場合、
v-model
のプロパティとイベントのデフォルト名が変更されました:- プロパティ:
value
->modelValue
; - イベント:
input
->update:modelValue
;
- プロパティ:
- 破壊的変更:
v-bind
の.sync
修飾子とコンポーネントのmodel
オプションは削除され、v-model
の引数に置き換わりました。 - 新機能: 同じコンポーネントに複数の
v-model
をバインドできるようになりました。 - 新機能: カスタム
v-model
修飾子を作成する機能が追加されました。
詳細については続きをお読みください!
はじめに
Vue 2.0 がリリースされたとき、v-model
ディレクティブは常に value
プロパティを使用する必要がありました。そして、別の用途のために別のプロパティが必要な場合は v-bind.sync
を使用しなければなりませんでした。さらに、この v-model
と value
のハードコードされた関係は、ネイティブ要素とカスタム要素の扱い方の問題につながりました。
2.2 では、コンポーネントが v-model
に使用するプロパティとイベントをカスタマイズできる、model
コンポーネントオプションを導入しました。しかしそれでもコンポーネント上で使用できる v-model
は 1 つだけでした。
Vue 3 では混乱を減らし、開発者がより柔軟に v-model
ディレクティブを使えるように、双方向データバインディングの API が標準化されました。
2.x の構文
2.x では、コンポーネントで v-model
を使用するのは、value
プロパティを渡して input
イベントを発行するのと同じでした:
<ChildComponent v-model="pageTitle" />
<!-- これは以下のショートハンド: -->
<ChildComponent :value="pageTitle" @input="pageTitle = $event" />
もし、プロパティやイベントの名前を別のものに変更したい場合は、ChildComponent
コンポーネントに model
オプションを追加する必要があります:
<!-- ParentComponent.vue -->
<ChildComponent v-model="pageTitle" />
// ChildComponent.vue
export default {
model: {
prop: 'title',
event: 'change'
},
props: {
// これにより `value` プロパティを別の目的で使用できます
value: String,
// `value` の代わりのプロパティとして `title` を使用
title: {
type: String,
default: 'Default title'
}
}
}
つまり、この場合の v-model
は、次のショートハンドになります:
<ChildComponent :title="pageTitle" @change="pageTitle = $event" />
v-bind.sync
の使用
場合によっては、(別のプロパティ用の既存の v-model
に加え)プロパティの「双方向バインディング」が必要になることがあります。そのためには、update:myPropName
のパターンでイベントを発行するのがお勧めです。例えば、前の例にあった title
プロパティを持つ ChildComponent
の場合、新しい値を割り当てる意図を伝えるには以下のようになります:
this.$emit('update:title', newValue)
その後、親はそのイベントを購読して、ローカルデータのプロパティを更新できます。例えば:
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
簡便のため、このパターンのショートハンドとして .sync
という修飾子があります:
<ChildComponent :title.sync="pageTitle" />
3.x の構文
3.x では、カスタムコンポーネントの v-model
は、modelValue
プロパティを渡して update:modelValue
イベントを発行するのと同じです:
<ChildComponent v-model="pageTitle" />
<!-- これは以下のショートハンド: -->
<ChildComponent
:modelValue="pageTitle"
@update:modelValue="pageTitle = $event"
/>
v-model
の引数
モデル名を変更するには、model
コンポーネントのオプションの代わりに、v-model
に引数を渡せるようになりました:
<ChildComponent v-model:title="pageTitle" />
<!-- これは以下のショートハンド: -->
<ChildComponent :title="pageTitle" @update:title="pageTitle = $event" />
これは、.sync
修飾子の代わりにもなり、カスタムコンポーネントに複数の v-model
を持たせることができるようになります。
<ChildComponent v-model:title="pageTitle" v-model:content="pageContent" />
<!-- これは以下のショートハンド: -->
<ChildComponent
:title="pageTitle"
@update:title="pageTitle = $event"
:content="pageContent"
@update:content="pageContent = $event"
/>
v-model
の修飾子
.trim
など、2.x のハードコードされた v-model
修飾子に加え、3.x ではカスタム修飾子がサポートされました:
<ChildComponent v-model.capitalize="pageTitle" />
詳細は、コンポーネントのカスタム v-model
修飾子をお読みください。
移行手順
推奨:
コードベースの
.sync
の使用を確認し、v-model
に置き換えます:html<ChildComponent :title.sync="pageTitle" /> <!-- 以下に置き換える --> <ChildComponent v-model:title="pageTitle" />
引数のないすべての
v-model
に対して、プロパティとイベント名をそれぞれmodelValue
とupdate:modelValue
に変更するhtml<ChildComponent v-model="pageTitle" />
js// ChildComponent.vue export default { props: { modelValue: String // 以前は `value: String` }, emits: ['update:modelValue'], methods: { changePageTitle(title) { this.$emit('update:modelValue', title) // 以前は `this.$emit('input', title)` } } }
COMPONENT_V_MODEL
COMPILER_V_BIND_SYNC
次のステップ
新しい v-model
構文の詳細については、以下を参照してください: