カスタムVue.jsコンポーネントにv-modelサポートを追加する方法

提供:Dev Guides
移動先:案内検索

序章

v-modelディレクティブは、Vue.jsにバンドルされている数少ないディレクティブの1つです。 このディレクティブにより、データとビュー間の双方向のデータバインディングが可能になります。

双方向のデータバインディングを使用すると、入力フィールドやその他のコントロールを介してデータを更新するときに、DOMの作業を行わなくてもDOM(ドキュメントオブジェクトモデル)を変更できます。

この記事では、このディレクティブがどのように機能するかを調べ、独自のコンポーネントに使用します。

v-modelが内部でどのように機能するかを理解する

HTMLの知識から、inputselect、および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はこの拡張を使用して、textareaselect、およびその他の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-modelpropおよび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" />

これを設定すると、コンポーネントの小道具やイベントを定義するときに競合を回避できます。

contenteditablev-modelを使用する

content editable 要素は、divまたは同様の要素であり、入力として機能するように構成できます。

contenteditable属性を要素に追加することにより、コンテンツの編集可能な要素を定義します。

<div class="editor" contenteditable="contenteditable"></div>

WYSIWYG エディターのコンテンツ編集可能要素は、操作が簡単で、大量のブラウザーでサポートされているため、使用します。

v-modelはコンテンツの編集可能な要素で機能しますが、要素のコンテンツを明示的に使用する必要があります。そうしないと、コンテンツが出力されません。

コンテンツを送信するには、divinnerTextまたはinnerHTMLを取得する必要があります。 したがって、updateInputメソッドは次のようになります。

updateInput () {
  this.$emit('input', this.$el.innerText)
}

ルート要素のコンテンツの代わりに、refのコンテンツを使用することもできます。

これを設定すると、v-modelはコンテンツの編集可能な要素に対して機能します。 updateInputメソッドでthis.contentを更新することもできます。

結論

カスタムVueコンポーネントでv-modelを使用する方法を確認したので、v-modelの使用を必要とするコンポーネントをビルドまたはリファクタリングすることができます。

詳細については、 v-model の公式ドキュメントを参照するか、Vue.jsトピックページでその他の演習やプロジェクトを確認してください。