カスタムコンポーネントでv-model使いたいのに難しくない?
公式のドキュメントをみてもパッと見つからないし、いろんなゴリ押し代替案があってコードが煩雑になる…
と思いきやカスタムコンポーネントでもきちんとv-modelを利用する綺麗な手法がありました。
ほぼ備忘録的な記事ですが、お役に立てれば幸いです。
#手順
すっ飛ばして見たい方はchildComponent.vue
のコードを参照してください。
model
プロパティという物が公式の機能にありました…いつ実装されたんだろうか。
ともかくこれをコンポーネント内で使います。
parentComponent.vue内でchildComponent.vueを使う構成です。
parentComponent.vue
<template>
<div class="parentComponent">
<childComponent v-model="modelvalue" />
</div>
</template>
<script>
import childComponent from 'path/to/childComponent'
export default {
components: {
childComponent,
},
data() {
return {
modelvalue: 'このプロパティをコンポーネント間で授受します。',
}
},
}
</script>
childComponent.vue
<template>
<div class="childComponent">
<input @input="emitValue" :value="modelvalue" />
</div>
</template>
<script>
export default {
//以下のmodelプロパティが今回の主役です。
model: {
prop: 'modelvalue',
event: 'emit-text'
},
//propsプロパティにmodelプロパティ内で指定したプロパティを作成
props: {
modelvalue: {
type: String //お好みのデータ型で
}
},
methods: {
emitText(e) {
//modelプロパティで指定したイベントをthis.$emitメソッドで飛ばします。
this.$emit('emit-text', e.target.value)
},
}
}
</script>
ちなみにtextarea
要素でも同様に動作します。textarea
要素には本来、value属性はありませんが上記のinput
要素と同じようにvalueへmodelvalue
をバインドすることでv-modelを利用できます。
注意点
- 上のコードを利用する場合、
childComponent.vue
のinput
タグ内にあるemitValue
をemitValue()
と記述しないようにしてください。イベントがメソッドに渡されず動きません。 -
childComponent.vue
のmodel
プロパティのprop
、event
の値は文字列で指定してください。