基礎からメモ: Vue.js CH3-p105 フォーム入力バインディング

v-modelディレクティブ

v-modelディレクティブを使って、フォームの入力値や選択値をデータと同期させる(双方向データバインディング)。

<div id="app">
  <input v-model="message" value="Vue"><br/>
  <p>{{ message }}</p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    message: "Hello!",
})

inputから入力した文字が、すぐ下の表示と同期する。日本語の場合は、変換が確定してから同期する。 v-modelディレクティブを使っている場合は、HTML側の属性で指定した値は無視される。上の例で言えば inputタグ のvalue="Vue"は反映されない。これは他のフォームのcheckedselectedでも同様。

v-modelは入力値を自動的に即座にデータに反映させるので、そのデータを使った表示は入力値の変更と同期して変わる。一方v-bindの場合は、データをHTML側に反映させはするが、フォームなどに使った場合、入力値を変更しても何らかの関数を介さないとデータまでは変更されない。

<input v-bind:value="message">
<p>{{ message }}</p>  <!-- inputの値の変更が、関数を介さないかぎり即座には反映されない -->

複数行テキスト

テキストエリアの値とデータの同期も同じやり方。

<textarea v-model="message"></textarea>
<pre>{{ message }}</pre>

ただしMustacheを使った書き方はできない。

<!-- これはできない-->
<textarea>{{ message }}</textarea>

チェックボックス

単一要素

単一要素のチェックボックスでは、Boolean型がデフォルト。

<label>
  <input type="checkbox" v-model="val"> {{ val }}
</label>
var app = new Vue({
  el: '#app',
  data: {
    val: true
})

単一要素にtruefalse以外の任意の値を設定したい場合、特殊な属性であるtrue-valuefalse-valueを使う。

<label>
  <input type="checkbox" v-model="val" true-value="yes" false-value="no"> {{ val }}
</label>
var app = new Vue({
  el: '#app',
  data: {
    val: ""
})

複数要素

複数のチェックボックスなどを並列させて複数選択を可能にした場合は、データ型は配列になる。

<label><input type="checkbox" v-model="val" value="A">A</label>
<label><input type="checkbox" v-model="val" value="B">B</label>
<label><input type="checkbox" v-model="val" value="C">C</label>
<p>{{ val }}</p>
var app = new Vue({
  el: '#app',
  data: {
    val: []
})

AとCを選択

[ "A", "C" ]

ラジオボタン

デフォルト値は文字列

<label><input type="radio" v-model="val" value="a">A</label>
<label><input type="radio" v-model="val" value="b">B</label>
<label><input type="radio" v-model="val" value="c">C</label>
<p>{{ val }}</p>
var app = new Vue({
  el: '#app',
  data: {
    val: ""
})

セレクトボックス

単一選択

デフォルト値は文字列

<select v-model="val">
  <option disabled="disabled">選択して下さい</option>
  <option value="a">A</option>
  <option value="b">B</option>
  <option value="c">C</option>
</select>
<p>{{ val }}</p>
var app = new Vue({
  el: '#app',
  data: {
    val: ""
})

複数選択

複数選択の場合はデータ型のデフォルトは配列

<select v-model="val" multiple>
  <option value="a">A</option>
  <option value="b">B</option>
  <option value="c">C</option>
</select>
<p>{{ val }}</p>
var app = new Vue({
  el: '#app',
  data: {
    val: []
})

画像ファイル

ボタンを使った画像ファイルの選択変更などで、ファイルタイプを扱うにはv-modelが使えない。データを同期させる(ファイル選択ボタンで選んだ画像を即刻表示させるなど)には、changeイベントをハンドルする。

<div id="app">
  <p>
    <input type="file" v-on:change="handleChange">
    <div v-if="preview"><img v-bind:src="preview"></div>
  </p>
</div>
var app = new Vue({
  el: '#app',
  data: {
    preview: '',
  },
  methods: {
    handleChange: function(event) {
      var file = event.target.files[0];
      if (file && file.type.match(/^image\/(png|jpeg)$/)) {
        this.preview = window.URL.createObjectURL(file);
      }
    }
  }
})

その他の入力タイプ

HTML5rangeタイプでハンドル付き数値バーを表示。

<input type="range" v-model.number="val">{{ val }}
var app = new Vue({
  el: '#app',
  data: {
    val: 50,
  }
})

input要素の入力値は文字列になるため、.number修飾子で数値化している。

v-modelで使える修飾子

.lazy inputのかわりにchangeイベントをハンドルする.

input要素で入力された値は、デフォルトでは入力された時点で、日本語では変換が確定した時点で同期するが、lazyを使うと changeイベントで同期する。テキストフォームではフォーカスが外れたりエンターが押されたときに同期する。

.number

input要素でtype="number"を指定しても、input の value属性は文字列として返る。.number修飾子を使うと、入力値を数値に変換してデータと同期させることができる。

.trim

文字列の前後に改行やスペースなどの余分な空白要素があった場合、削除してから同期させる。