LoginSignup
0
0

More than 3 years have passed since last update.

Vue.jsのフォーム入力バインディング

Last updated at Posted at 2021-04-20

入力フィールド

テキストボックス

<input type="text" v-model="message">
<p>{{ message }}</p>
data() {
  return {
    message: 'test',
  }
}

テキストエリア

<textarea v-model="message"></textarea>
<p>{{ message }}</p>
data() {
  return {
    message: 'test\ntest',
  }
}

単体チェックボックス

<input type="checkbox" id="test-cb" v-model="checked">
<label for="test-cb">{{ checked ? "checked" : "unchecked" }}</label>
data() {
  return {
    checked: false,
  }
}

複数チェックボックス

チェックするとlanguagesに対象のチェックボックスのvalueの値が格納され、
チェックを外すとlanguagesから対象のチェックボックスのvalueの値が削除される。

<input type="checkbox" id="javascript" value="JavaScript" v-model="languages">
<label for="javascript">JavaScript</label>
<input type="checkbox" id="golang" value="Go" v-model="languages">
<label for="golang">Go</label>
<input type="checkbox" id="ruby" value="Ruby" v-model="languages">
<label for="ruby">Ruby</label>
data() {
  return {
    languages: [],
  }
}

ラジオボタン

<input type="radio" id="javascript" value="JavaScript" v-model="language">
<label for="javascript">JavaScript</label>
<input type="radio" id="golang" value="Go" v-model="language">
<label for="golang">Go</label>
<input type="radio" id="ruby" value="Ruby" v-model="language">
<label for="ruby">Ruby</label>
data() {
  return {
    language: '',
  }
}

単体セレクトボックス

<select v-model="language">
  <option disabled value="">Select language</option>
  <option value="javascript">JavaScript</option>
  <option value="golang">Go</option>
  <option value="ruby">Ruby</option>
</select>
data() {
  return {
    language: '',
  }
}

複数セレクトボックス

選択するとlanguagesに対象の選択肢のvalueの値が格納され、
選択を外すとlanguagesから対象の選択肢のvalueの値が削除される。

<select v-model="languages" multiple>
  <option disabled value="">Select languages</option>
  <option value="javascript">JavaScript</option>
  <option value="golang">Go</option>
  <option value="ruby">Ruby</option>
</select>
data() {
  return {
    languages: [],
  }
}

修飾子

.lazy

データの同期を遅延する。
入力時には同期されず、enterキーやtabキー、他の要素をクリックするなどすると、データが同期される。

<input type="text" v-model.lazy="message">
<p>{{ message }}</p>
data() {
  return {
    message: 'test',
  }
}

.number

入力値をNumberとして自動的に型変換してからデータを同期する。
inputtypenumberを指定しても、常に文字列が返されるため、入力値をそのまま計算に使いたい時などに有用。
内部的にはparseFloat()を使っていて、変換できない場合は元の入力値が返される。

<input type="number" v-model.number="height">
<p>{{ height + 10 }}</p>
data() {
  return {
    height: 170,
  }
}

.trim

入力値の前後の空白を除去してからデータを同期する。
全角でも半角でも除去される。

<input type="text" v-model.trim="message">
<p>{{ message }}</p>
data() {
  return {
    message: 'test',
  }
}

カスタム入力

v-modelはコンポーネントに対しても利用することができる。

<custom-input v-model="message"></custom-input>

custom-inputのコードを書く前に、以下の2つのコードが同等であるということを理解する。

<input v-model="message">
<input :value="message" @input="message = $event.target.value">

データの単方向バインド(:value="message")とイベントをハンドルする処理(@input="message = $event.target.value")の組み合わせを、
双方向バインディング(v-model)が行っているということがわかる。

v-modelをコンポーネントに対して利用する場合、Vueは下記が同等となるように動作する。

<custom-input v-model="message"></custom-input>
<custom-input :value="message" @input="message = $event"></custom-input>

ここで大事になるのが、以下の2点である。

  • valueというpropsがcustom-inputに渡されている
  • inputイベントのハンドラは、$event.target.valueではなく$eventをバインドされているデータ(message)に代入している

すると、通常のフォーム入力バインディングと同じように動作するためには、下記のようにcustom-inputを実装する必要があるとわかる。

  • propsのvalueinput要素のvalueにバインドする(単方向バインディング)
  • inputイベントのハンドラで、inputイベントを入力値と共に親コンポーネントに通知する
var CustomInput = {
  template: `<input :value="value" @input="$emit('input', $event.target.value)">`,
  props: {
    value: String
  }
}

上記のように実装すると、本項の初めに書いたように

<custom-input v-model="message"></custom-input>
components: {
  'custom-input': CustomInput
},
data() {
  return {
    message: 'test',
  }
}

と利用することができる。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0