入力フィールド
テキストボックス
<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
として自動的に型変換してからデータを同期する。
input
のtype
にnumber
を指定しても、常に文字列が返されるため、入力値をそのまま計算に使いたい時などに有用。
内部的には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の
value
をinput
要素の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',
}
}
と利用することができる。