# フォーム入力バインディング
# 基本的な使い方
form の input 要素や textarea 要素、 select 要素に双方向データバインディングを付与するためには、v-model
を使用することができます。v-model
は、要素を更新する適切な方法を入力の種類に基づき自動的に選択します。少し魔法のようですが、本来v-model
は糖衣構文(syntax sugar)であり、ユーザの入力イベントに応じてデータを更新し、さらにエッジケースに対する特別な配慮をしてくれます。
TIP
v-model
はフォーム要素のvalue
属性やchecked
属性、selected
属性の初期値を無視します。v-model
は常に、現在アクティブなインスタンスのdata
を信頼できる情報源として扱います。初期値の宣言は JavaScript 側、コンポーネントのdata
オプション内で行ってください。
内部的には、v-model
は異なる input 要素に対し異なるプロパティを使用し、異なるイベントを送出します。
- text および textarea 要素には、
value
プロパティとinput
イベントを用います - チェックボックスおよびラジオボタンには、
checked
プロパティとchange
イベントを用います - select フィールドには、
value
プロパティとchange
イベントを用います
Note
IME (opens new window)を必要とする言語 (中国語、日本語、韓国語など) においては、IME による入力中に v-model
が更新を行わないことに気づくでしょう。このような更新にも対応したい場合、 v-model
をつかう代わりに input
イベントリスナと value
のバインディングを使ってください。
# テキスト
<input v-model="message" placeholder="edit me" />
<p>Message is: {{ message }}</p>
2
# 複数行テキスト
<span>Multiline message is:</span>
<p style="white-space: pre-line;">{{ message }}</p>
<br />
<textarea v-model="message" placeholder="add multiple lines"></textarea>
2
3
4
textarea への挿入は機能しません。代わりにv-model
を用いてください。
<!-- bad -->
<textarea>{{ text }}</textarea>
<!-- good -->
<textarea v-model="text"></textarea>
2
3
4
5
# チェックボックス
単一のチェックボックスと boolean 値:
<input type="checkbox" id="checkbox" v-model="checked" />
<label for="checkbox">{{ checked }}</label>
2
同じ配列にバインドされた複数のチェックボックス:
<div id="v-model-multiple-checkboxes">
<input type="checkbox" id="jack" value="Jack" v-model="checkedNames" />
<label for="jack">Jack</label>
<input type="checkbox" id="john" value="John" v-model="checkedNames" />
<label for="john">John</label>
<input type="checkbox" id="mike" value="Mike" v-model="checkedNames" />
<label for="mike">Mike</label>
<br />
<span>Checked names: {{ checkedNames }}</span>
</div>
2
3
4
5
6
7
8
9
10
Vue.createApp({
data() {
return {
checkedNames: []
}
}
}).mount('#v-model-multiple-checkboxes')
2
3
4
5
6
7
# ラジオ
<div id="v-model-radiobutton">
<input type="radio" id="one" value="One" v-model="picked" />
<label for="one">One</label>
<br />
<input type="radio" id="two" value="Two" v-model="picked" />
<label for="two">Two</label>
<br />
<span>Picked: {{ picked }}</span>
</div>
2
3
4
5
6
7
8
9
Vue.createApp({
data() {
return {
picked: ''
}
}
}).mount('#v-model-radiobutton')
2
3
4
5
6
7
# セレクト
単一のセレクト:
<div id="v-model-select" class="demo">
<select v-model="selected">
<option disabled value="">Please select one</option>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
2
3
4
5
6
7
8
9
Vue.createApp({
data() {
return {
selected: ''
}
}
}).mount('#v-model-select')
2
3
4
5
6
7
Note
v-model
の式の初期値がいずれのオプションとも一致しない場合、<select>
要素は 未選択 の状態で描画されます。これにより iOS では最初のアイテムが選択できなくなります。なぜなら iOS はこのような場合に change
イベントを発火させないためです。したがって、上記の例で示したように、value
を持たないdisabled
なオプションを追加しておくことをおすすめします。
複数個のセレクト(配列にバインド):
<select v-model="selected" multiple>
<option>A</option>
<option>B</option>
<option>C</option>
</select>
<br />
<span>Selected: {{ selected }}</span>
2
3
4
5
6
7
動的なオプションをv-for
により描画:
<div id="v-model-select-dynamic" class="demo">
<select v-model="selected">
<option v-for="option in options" :value="option.value">
{{ option.text }}
</option>
</select>
<span>Selected: {{ selected }}</span>
</div>
2
3
4
5
6
7
8
Vue.createApp({
data() {
return {
selected: 'A',
options: [
{ text: 'One', value: 'A' },
{ text: 'Two', value: 'B' },
{ text: 'Three', value: 'C' }
]
}
}
}).mount('#v-model-select-dynamic')
2
3
4
5
6
7
8
9
10
11
12
# 値のバインディング
ラジオやチェックボックス、セレクトの option において、v-model
でバインディングされる値は通常は静的な文字列(チェックボックスの場合は boolean も)です:
<!-- チェックされているとき`picked` は文字列"a"になります -->
<input type="radio" v-model="picked" value="a" />
<!-- toggle` は true または false のどちらかです -->
<input type="checkbox" v-model="toggle" />
<!-- 最初のオプションが選択されているとき`selected` は文字列"abc"です -->
<select v-model="selected">
<option value="abc">ABC</option>
</select>
2
3
4
5
6
7
8
9
10
しかし、現在アクティブなインスタンスの動的なプロパティに値をバインドしたいときがあるかもしれません。それを実現するためにはv-bind
を使用できます。さらに、v-bind
を使用することで入力値に文字列以外の値もバインドできるようになります。
# チェックボックス
<input type="checkbox" v-model="toggle" true-value="yes" false-value="no" />
// チェックされているとき:
vm.toggle === 'yes'
// チェックされていないとき:
vm.toggle === 'no'
2
3
4
Tip
true-value
と false-value
属性は input の value
属性には影響を及ぼしません。なぜならブラウザはチェックされていないチェックボックスをフォーム送信内容には含めないためです。二つの値(例: "yes" または "no")のうち一つが必ず送信されることを保証するには、代わりにラジオを使用してください。
# ラジオ
<input type="radio" v-model="pick" v-bind:value="a" />
// チェックされているとき:
vm.pick === vm.a
2
# セレクトオプション
<select v-model="selected">
<!-- インラインオブジェクトリテラル -->
<option :value="{ number: 123 }">123</option>
</select>
2
3
4
// 選択されているとき:
typeof vm.selected // => 'object'
vm.selected.number // => 123
2
3
# 修飾子
# .lazy
デフォルトではv-model
は各input
イベント後に入力値とデータを同期します(上述の IME 入力の例外はあります)。lazy
修飾子を加えることで、change
イベント後に同期するよう変更できます。
<!-- "input" ではなく "change" イベントの後に同期されます -->
<input v-model.lazy="msg" />
2
# .number
ユーザ入力を自動的に number へ型キャストさせたい場合は、v-model
で管理している input にnumber
修飾子を加えることができます。
<input v-model.number="age" type="number" />
これはしばしば有用です。なぜならtype="number"
が書いてあったとしても HTML の input 要素は常に文字列を返すためです。値がparseFloat()
でパースできない場合は、元々の値が返却されます。
# .trim
ユーザ入力から空白を自動で取り除きたい場合は、v-model
で管理している input に trim
修飾子を加えることができます。
<input v-model.trim="msg" />
# コンポーネントのv-model
まだ Vue コンポーネントに慣れていない場合、この節は一旦スキップすることができます。
HTML 組み込みの input タイプが、常にあなたのニーズに適っているとは限りません。幸運にも、Vue コンポーネントによって、動作を隅々までカスタマイズ可能な再利用性のある入力フォームを自作することができます。それらのフォームにv-model
を使うことも可能です!詳しくは、コンポーネントガイドの カスタム input を参照してください。
← イベントハンドリング コンポーネントの基本 →