カスタムVue.jsコンポーネントにv-modelサポートを追加する方法
序章
v-model
ディレクティブは、Vue.jsにバンドルされている数少ないディレクティブの1つです。 このディレクティブにより、データとビュー間の双方向のデータバインディングが可能になります。
双方向のデータバインディングを使用すると、入力フィールドやその他のコントロールを介してデータを更新するときに、DOMの作業を行わなくてもDOM(ドキュメントオブジェクトモデル)を変更できます。
この記事では、このディレクティブがどのように機能するかを調べ、独自のコンポーネントに使用します。
v-model
が内部でどのように機能するかを理解する
HTMLの知識から、input
、select
、およびtextarea
がアプリケーションにデータを供給する主な方法であることがわかります。
v-model
が機能するためには、問題の要素またはコンポーネントが小道具(デフォルトはvalue
)を受け取り、イベント(デフォルトはinput
)を発行することを期待します。
要素に応じて、Vueはデータをリッスンして処理する方法を決定します。 input
要素の場合、次のようにv-model
を使用できます。
<input v-model="email" />
v-model
はこれに変換されます:
<input :value="email" @input="e => email = e.target.value" />
Vueはこの拡張を使用して、textarea
、select
、およびその他のinput
タイプを処理します。
ラジオボタンとチェックボックスの場合、Vueはchecked
プロップを使用して、change
イベントをリッスンします。
select
タグや複数の値を受け入れることができるチェックボックスなどの要素の場合、Vueは選択された値の配列を自動的に返します。
カスタムコンポーネントへのv-model
の追加
コンポーネントがv-model
双方向バインディングをサポートできるようにするには、コンポーネントはvalue
プロップを受け入れ、input
イベントを発行する必要があります。
basic-input
というサンプルコンポーネントを作成しましょう。 Vueの単一ファイルコンポーネントを使用します。
basic-input.vue
<template> <input @input="handleInput" /> </template> <script> export default { prop: ['value'], data () { return { content: this.value } }, methods: { handleInput (e) { this.$emit('input', this.content) } } } </script>
v-model
をサポートするために、コンポーネントはvalue
プロップを受け入れ、input
イベントを発行します。
次のようなコンポーネントを使用します。
<basic-input v-model="email" />
これにより、カスタムコンポーネントはv-model
双方向バインディングをサポートします。
v-model
prop
およびevent
のカスタマイズ
さらに一歩進んでみましょう。 コンポーネントにv-model
サポートを追加するために必要なデフォルトのevent
およびprop
を使用したくない場合があります。 ありがたいことに、Vueではカスタマイズが可能です。
event
と``propをカスタマイズするには、model
プロパティをコンポーネントに追加し、次のように新しい値を定義します。
basic-input.vue
// ... export default { prop: ['hidden'], model: { prop: 'hidden', event: 'blur' } methods: { handleInput (value) { this.$emit('blur', value) } } } // ...
今回は、次のようなコンポーネントを使用すると、次のようになります。
<basic-input v-model="email" />
Vueは自動的に次のように変換します。
<basic-input :hidden="email" @blur="e => email = e.target.value" />
これを設定すると、コンポーネントの小道具やイベントを定義するときに競合を回避できます。
contenteditable
でv-model
を使用する
content editable 要素は、div
または同様の要素であり、入力として機能するように構成できます。
contenteditable
属性を要素に追加することにより、コンテンツの編集可能な要素を定義します。
<div class="editor" contenteditable="contenteditable"></div>
WYSIWYG エディターのコンテンツ編集可能要素は、操作が簡単で、大量のブラウザーでサポートされているため、使用します。
v-model
はコンテンツの編集可能な要素で機能しますが、要素のコンテンツを明示的に使用する必要があります。そうしないと、コンテンツが出力されません。
コンテンツを送信するには、div
のinnerText
またはinnerHTML
を取得する必要があります。 したがって、updateInput
メソッドは次のようになります。
updateInput () { this.$emit('input', this.$el.innerText) }
ルート要素のコンテンツの代わりに、refのコンテンツを使用することもできます。
これを設定すると、v-model
はコンテンツの編集可能な要素に対して機能します。 updateInput
メソッドでthis.content
を更新することもできます。
結論
カスタムVueコンポーネントでv-model
を使用する方法を確認したので、v-model
の使用を必要とするコンポーネントをビルドまたはリファクタリングすることができます。
詳細については、 v-model の公式ドキュメントを参照するか、Vue.jsトピックページでその他の演習やプロジェクトを確認してください。