Vue.jsにはinputタグやtextarea、selectタグなどで使えるv-modelという非常に便利な機能(ディレクティブ)が用意されています。
v-modelを使うとVue.jsのデータとHTML上のデータを連動されることができます。
ここではv-moldeの使い方や注意点、v-bindとの違い、実際にinputタグやtextareaタグ、selectタグで使う方法を実例を踏まえて解説しています。
また、v-modelの便利な修飾子についても使い方をまとめています。
v-modelとは何か?
v-modelとはVue.jsのディレクティブの1種です。Vue.jsのデータとHTML上のデータを連動させることができます。
双方向データバインディングとは何か?
v-modelを使うことで、Vue.jsのデータをHTMLに渡せます。ブラウザ上に表示されている該当するデータを編集すると、Vue.js側のデータを書き換えることができます。
Vue.js→HTMLだけでなく、HTML→Vue.jsの双方向でデータが連動しているため、v-modelのことを「双方向データバインディング」と呼びます。
v-bindとv-modelは何が違うか?
v-modelディレクティブと似た機能に、v-bindディレクティブがあります。v-bindはVue.jsのデータをHTMLに渡すのみです。Vue.js→HTMLの単方向のみで機能するので、単方向データバインディングと呼びます。
「双方向データバインディング」「単方向データバインディング」という言葉は聞きなれず、一見難しいように聞こえますが、ただデータの受け渡しの流れを言葉(英語と日本語)で示しているだけのシンプルなものです。
v-bindとv-modelは似ていますが、使い方に違いがあるため注意が必要です。
v-modelが使用できるタグ
v-modelは使用できるタグが限られています。HTML→Vue.jsのデータ操作を可能にするため、v-modelが使えるのは、画面上でユーザーが操作できるタグです。
v-modelを使うメリット
inputタグはtype=”text”やtextareaでv-modelを使うメリットは、ユーザーが入力した内容をデータとして所持できることです。他の場所やページで呼び出すことが可能になります。あるいは、他のページで入力された内容を反映するなど、動的に変更することもできるようになります。
inputタグはtype="text"
の入力ボックス以外にも、タイプを変更することでチェックボックスやラジオボタンなどになります。これらのタイプの異なる要素でもv-modelが使えます。
チェックボックスやラジオボタン、Selectタグでv-modelを使う主なメリットは①デフォルトで選択済にする要素を指定できる。②現在選択中の要素が何かわかることです。
v-modelの使用時の注意点
v-modelとv-bindの書き方の違い
v-modelを使う時は使用できるタグと連動する属性が限られているため、v-bindと異なり属性名を省略した表記となります。
項目 | 代表的な使い方 | 省略形 |
---|---|---|
v-model | v-model=”プロパティ名” | なし |
v-bind | v-bind:属性名=”プロパティ名” | :属性名=”プロパティ名” |
inputタグの入力ボックスの場合、v-modelはvalueと連動していることが暗示された形になっています。
よくある間違い
v-bindの感覚でv-modelを使うと、v-model:value="プロパティ名"
といった書き方をしてしまいがちですが、これはエラーになるので注意が必要です。
valueが無視されるときと必要なときがある
v-modelを使う時に混乱を発生するのが、inputタグのタイプによってvalueを記述すると無視される場合と、valueが必須の場合があることです。
選択肢が一つの場合valueは無視される
inputタグのtype="text"
やtextareaなどの場合、v-model=”プロパティ名”とは別に、value=”値”を記載すると、valueは無視されます。
inputタグのvalue無視事例
参考にinputタグでvalueが無視される事例を記載しておきます。
var app = new Vue({
el:'#app',
data:{
message: "テストメッセージ"
}
})
<body>
<div id="app">
<p>value属性無視の事例</p>
<p>プロパティの状態:{{ message }}</p>
<input type="text" v-model="message" value="valueの初期値">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
上記HTMLの場合、inputタグにv-modelとvalueの両方を設置していますが、valueは無視されます。
<input type="text" v-model="message" value="valueの初期値">
▼ブラウザの表示
value="valueの初期値"
は無視され、Vue.js側で設定しv-modelで指定したmessage: "テストメッセージ"
が表示されます。
なお、valueの設定が必須な場合の例については下の方で実例を紹介しています。
textareaでv-modelを使う方法と注意点
v-modelを使えば、textareaにVue.jsのデータを表示して、HTML側でユーザーが編集するのに合わせてVue.jsのデータを連動して変更することができます。
使い方
使い方はシンプルでv-model="プロパティ名"
で連動させたいVue.jsのデータを指定するのみです。
<textarea v-model="プロパティ名"></textarea>
inputタグと異なり終了タグが必要です。
注意点
textareaでv-modelを使う場合、開始タグと終了タグの間にマスタッシュ構文 {{ }} でプロパティを呼び出す必要はありません。
v-model=”プロパティ名”を記載すれば、プロパティの値が初期値としてtextareaに表示されます。
実例
textareaでv-modelを使う正しい使い方は以下のようになります。
var app = new Vue({
el:'#app',
data:{
message: "テストメッセージ"
}
})
<body>
<div id="app">
<p>プロパティの値:{{ message }}</p>
<div>
<textarea name="" v-model="message"></textarea>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
▼ブラウザの表示
デフォルトではv-modelで指定したプロパティの値がtextareaに表示されます。
↓ メッセージを編集
textareaの内容を書き変えるたびに、プロパティの値も置き換わっていることがわかります。
v-modelを使ってtextareaの中の文章を改行したい場合
v-modelを使ってtextareaの中の文章を改行したい場合は「\n」を入力します。
▼実例
message: "初期\nメッセージ",
上記のようにすると画面上の表示は「初期」で改行したものになります。
var app = new Vue({
el:'#app',
data:{
message: "初期\nメッセージ",
}
})
なお、画面上のtextareaで改行した場合も「\n」がプロパティに挿入されます。
よくある間違いの実例
参考としてv-modelしていない場合や、タグの間のテキストやマスタッシュ構文が無視される場合のコードを記載
var app = new Vue({
el:'#app',
data:{
message: "テストメッセージ"
}
})
<body>
<div id="app">
<div>
<p>■textareaの注意点</p>
<p>プロパティの値:{{ message }}</p>
<br>
<p>①マスタッシュ構文のみ</p>
<textarea name="" >{{message}}</textarea>
<br><br>
<p>②v-modelによる記述</p>
<textarea name="" v-model="message">AAAAA</textarea>
<br><br>
<p>③マスタッシュ構文とv-modelの併用</p>
<textarea name="" v-model="message">{{dummy}}</textarea>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
▼ブラウザの表示
①ではtextareaのメッセージを編集しても、プロパティの値が置き換わりません。
②はtextareaタグの間に記載しているテキスト「AAAAA」が無視されています。
③はtextareaタグの間に記載しているマスタッシュ構文 {{ dummy }} が無視されています。
チェックボックスでv-modelを使う方法と注意点
チェックボックスでv-modelを使う場合は、v-modelがchecked属性の代わりになります。
チェックできる項目が一つだけの場合と、選択項目が複数ある場合でデータの持たせ方や属性の記載方法が異なるので注意が必要です。
選択項目の数 | プロパティの値 | タグの属性 |
---|---|---|
1つ | 真偽値(true/false) | value属性は不要 |
複数 | 配列 | value属性が必須 |
選択項目が1つだけのチェックボックス
使い方と注意点
選択項目が1つだけのチェックボックスの場合、v-model=”プロパティ名”とし、プロパティの値を真偽値(true or false)にします。
プロパティの値がtrueの時はチェックあり、チェックを外すとプロパティの値がfalseになります。
デフォルトでチェック無しにしたい場合は、プロパティの値をfalseにしておきます。
実例
var app = new Vue({
el:'#app',
data:{
//checkboxの状態
isChecked: true
}
})
<body>
<div id="app">
<p>■checkboxでv-modelを使う</p>
<input type="checkbox" id="checkbox1" v-model="isChecked">
<label for="checkbox1">プロパティの値:{{isChecked}}</label>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
▼ブラウザの表示
デフォルトではv-modelでつないでいるisCheckedプロパティの値がtrueなので、チェックありになります。
↓ チェックを外す
チェックを外したことで、isCheckedプロパティの値がfalseに変わっています。
↓ チェックをつける
再度チェックをつけると、isCheckedプロパティの値がfalse→trueに切り替わります。
複数のチェックボックスでv-modelを使う方法
使い方と注意点
複数のチェックボックスの場合はVue.js側でプロパティの持たせ方と、タグの属性の設定方法が異なります。
ポイントとしては、配列内にvalueの値を記述するとチェックマークがつきます。配列が空欄の場合、すべてチェックマークなしの状態になります。
inputタグは次のようになります。
<input type="checkbox" v-model="プロパティ名" value="固有の値">
実例
id名がblue, redgreen,green,の3つのチェックボックスを用意して、初期状態で、blueとgreenにチェックマークが入った状態をつくる場合は以下のようになります。
var app = new Vue({
el:'#app',
data:{
//複数のcheckbox
multiChecked: ["blue", "Green"]
}
})
<body>
<div id="app">
<p>■checkboxでv-modelを使う</p>
<input type="checkbox" id="red" v-model="multiChecked" value="red">
<label for="red">Red</label>
<input type="checkbox" id="blue" v-model="multiChecked" value="blue">
<label for="blue">Blue</label>
<input type="checkbox" id="green" v-model="multiChecked" value="green">
<label for="green">Green</label>
<br>
<p>プロパティの値: {{multiChecked}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
▼ブラウザの表示
デフォルトではv-modelで選択しているmultiCheckedプロパティの値が["blue", "green"]
なので、該当するid名のチェックボックスがチェック済みになります。
↓ Redにチェックマークを入れる。
multiCheckedプロパティの値が["blue", "green", "red"]
になっていることに注目してください。
↓ 全てのチェックマークを外す。
全てのチェックマークを外すと、multiCheckedプロパティの値は空の配列[]
になります。
ラジオボタンでv-modelを使う方法
チェックボックスと違い、一つの項目のみしか選択できない仕様のラジオボタンでv-modelを使うと、現在選択中の要素が何かを判定することができます。
ラジオボタンは、各要素に固有のvalueを割当てます。v-modelで指定したプロパティの値とvalueの値が連動します。
inputタグは以下のようになります。
<input type="radio" v-model="プロパティ名" value="固有の値">
実例
good, normal, badの3つのラジオボタンを用意し、デフォルトでnormalを選択状態にする場合は以下のようになります。
var app = new Vue({
el:'#app',
data:{
//ラジオボタン
radio: 'normal'
}
})
<body>
<div id="app">
<p>■ラジオボタンとv-model</p>
<input type="radio" id="good" v-model="radio" value="good">
<label for="good">good</label>
<input type="radio" id="normal" v-model="radio" value="normal">
<label for="normal">normal</label>
<input type="radio" id="bad" v-model="radio" value="bad">
<label for="bad">bad</label>
<p>プロパティの値: {{radio}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
ブラウザの表示
デフォルトではnormalが選択されています。下部に表示しているプロパティの値もnormalになっていることがわかります。
↓ goodを選択する
プロパティの値がgoodに変わりました。
↓ badを選択する。
プロパティの値がbadに変わりました。
セレクトボックスでv-modelを使う方法
使い方と注意点
selectタグにv-model="プロパティ名"
を記述することで、選択した内容をプロパティに反映させることができます。
selectタグの中に記述するoptionタグにv-modelを設置する必要はありません。
選択可能な項目が1つの場合と、複数選択可能な場合でVue.jsのプロパティの値が異なるので注意が必要です。
また、初期値を設定するときに、選択可能な項目の中から選ぶ場合と、説明など初期値は選択不可にする場合でタグの記述方法とプロパティで指定する値が異なります。
初期値の設定方法
selectタグで最初から何かの値を選択済にしておく場合、(1)選択肢の中から選ぶ場合と(2)選択肢以外の専用の値を設定する場合で設定の仕方が異なります。
(1)選択肢の中から選ぶ場合
初期表示したいoputionタグのテキストをv-modelでつないだプロパティの値に記述します。
(2)選択肢以外の専用の値を設定する場合
初期値は表示のみで選択できないようにするには、該当するoptionタグを用意し、disabled属性と、value属性の2つを設定する必要があります。
<option disabled value="プロパティの値">Please Select</option>
その上で、v-modelで指定したプロパティの値を上記のvalueの値にする必要があります。
実例:初期値を選択肢の中から選ぶ場合
初期表示したいoputionタグのテキストをプロパティの値に記述します。
例えば、以下のように3つの選択項目を用意して、デフォルトで2番目の値を選択した状態にするには、v-modelで指定しているプロパティselected2の値に、2番目のオプションタグのテキスト「2つ目の項目」を指定します。
<body>
<div id="app">
<p>選択肢の中から初期値を選ぶ</p>
<select v-model="selected2">
<option>1つ目の項目</option>
<option>2つ目の項目</option>
<option>3つ目の項目</option>
</select>
<p>プロパティの値: {{selected2}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
参考として、下部にプロパティの値を{{ selected2 }}
で表示しています。
var app = new Vue({
el:'#app',
data:{
//セレクトボックス
selected2: '2つ目の項目',
}
})
▼ブラウザの表示
デフォルトの状態はプロパティの値に指定したテキストと対応するoptionタグが選択されています。
↓ プルダウンで「3つ目の項目」を選択
他の要素を選択すれば、そのoptionタグのテキストの値がプロパティの値に置き換わります。
実例:専用の初期値を設定する場合
初期値は表示のみで選択できないようにするには、該当するoptionタグを用意し、disabled属性と、value属性の2つを設定する必要があります。
<option disabled value="プロパティの値">Please Select</option>
その上で、v-modelで指定したプロパティの値を上記のvalueの値にする必要があります。
例えば、4つのoptionタグを用意して、一番上のdisabled属性をつけた要素を初期表示のみ・選択不可にする場合は次のようになります。
<body>
<div id="app">
<p>専用の初期値を設定する</p>
<select v-model="selected3">
<option disabled value="initial">Please Select</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<p>プロパティの値: {{selected3}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
参考として、下部にプロパティの値を{{ selected3 }}
で表示しています。
var app = new Vue({
el:'#app',
data:{
//セレクトボックス
selected3: 'initial',
}
})
v-modelで指定した、プロパティselected3の値を、disabledを設定したoptionタグのvalue属性の値にしています。
▼ブラウザの表示
↓ プルダウンをクリック
プルダウンをクリックすると初期値で表示していた項目がグレーアウトして選択できないようになっています。
↓ 3を選択
3を選択すると、プロパティの値が選択した内容に置き換わります。
セレクトボックスとv-modelの実例確認用コード
参考として、セレクトボックスでv-modelを使う確認用のコードを記載しておきます。以下の3つのパターンを試すこととができます。
- 初期値無し。
- 選択肢の中から初期値を選ぶ。
- 専用の初期値を設定する(初期値は選択不可にする)
<body>
<div id="app">
<p>セレクトボックスとv-model</p>
<p>①初期選択無し</p>
<select v-model="selected1">
<option>1つ目の項目</option>
<option>2つ目の項目</option>
<option>3つ目の項目</option>
</select>
<p>プロパティの値: {{selected1}}</p>
<br><br>
<p>②選択肢の中から初期値を選ぶ</p>
<select v-model="selected2">
<option>1つ目の項目</option>
<option>2つ目の項目</option>
<option>3つ目の項目</option>
</select>
<p>プロパティの値: {{selected2}}</p>
<br><br>
<p>③専用の初期値を設定する</p>
<select v-model="selected3">
<option disabled value="initial">Please Select</option>
<option>1</option>
<option>2</option>
<option>3</option>
</select>
<p>プロパティの値: {{selected3}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
var app = new Vue({
el:'#app',
data:{
//セレクトボックス
selected1: '',
selected2: '2つ目の項目',
selected3: 'initial',
}
})
▼ブラウザの表示
複数選択可能なセレクトボックスでv-modelを使う方法
使い方と注意点
セレクトボックスで複数選択を可能にする場合、selectタグの属性にmultipleを付与すると複数選択可能になります。
その際、単数選択のときと異なりv-modelで指定するプロパティの値を配列にする必要があります。
▼タグの属性に multipleを記述
<select v-model="プロパティ名" multiple>
▼プロパティの値は配列にする
var app = new Vue({
el:'#app',
data:{
//複数選択可能なセレクトボックス
multiSelect: []
}
})
初期値の設定方法
複数選択可能なセレクトボックスの初期値は以下の4つのパターンが考えられます。
- 初期値を設定しない: 配列を空にする。
- 初期値を1つ設定する :配列に該当するoptionタグのテキストを入れる。
- 初期値を複数設定する :配列に該当する複数のoptionタグのテキストを並列に入れる。
- 選択不可能な項目を表示する :disabledを設定したoptionタグを作る。
実例
複数選択可能なセレクトボックスでv-modelを使う例として、選択不可能なoptionタグと、初期値として「111」と「BBB」が記載された2つのoptionタグを選択済にする場合は以下のようになります。
<body>
<div id="app">
<div>
<p>■複数選択可能なセレクトボックス</p>
<select v-model="multiSelect" multiple>
<option disabled>Please Select</option>
<option>111</option>
<option>BBB</option>
<option>333</option>
<option>DDD</option>
<option>555</option>
</select>
<p>プロパティの値: {{ multiSelect }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
参考として、下部にプロパティの値を{{ multiSelect }}
で表示しています。
var app = new Vue({
el:'#app',
data:{
//複数選択可能なセレクトボックス
multiSelect: [ 111,'BBB' ]
}
})
▼ブラウザの表示
デフォルトで「111」と「BBB」が選択済になっています。
↓ 「111」と「BBB」以外を選択する。
選択済の項目がプロパティの値になっています。
v-modelの修飾子
修飾子の使い方
v-modelには合わせてよく使う処理が、修飾子として用意されています。修飾子は以下のように使います。
v-model.修飾子="プロパティ名"
修飾子の一覧
v-modelで使える修飾子は lazy, trim, numberの3つです。
修飾子 | 概要 |
---|---|
.lazy | バインドのタイミング(プロパティへの反映)を遅らせる |
.trim | 入力値の空白を除外してプロパティに代入する |
.number | 入力値を数値型に変換してから代入する |
参考リンク: 公式ページ
.lazy
通常のリアルタイム反映(日本語の場合は確定後の反映)から、Enterで確定やTABキーで要素から移動した場合への反映となります。
lazyを設定しないと、アルファベットや数値を1文字入力したり、文字を1つ消すごとにプロパティの値が置き換わる処理を回避することができます。
v-model.lazy="プロパティ名"
.trim
入力値から、前後の空白(全角・半角)を削除して、プロパティに反映します。
※中間の空白は2つ以上の場合に1つのみとなります。
例: 「 you good 」→「you good」
.number
v-model.number
とすることでデータバインディングしているプロパティに格納される値が数値型になります。
inputタグでtype=”text”とv-model.numberを併用した場合、数値のみの場合は数値として、文字を含む場合は文字列として扱われます。
実例:入力値を使って数値計算する場合の注意点(.numberの重要性)
number修飾子は入力された数値に対して計算処理を行う場合は必須となります。
例え、inputタグのtypeをnumberにしていたとしても、計算処理を行うと期待通りの結果にはなりません。なぜなら、typeをnumberであってもv-modelを使うとプロパティに保存される値は文字列になるためです。
よって、.numberがない場合、入力値が「11」に対して「10」を足すと、「1110」のように表示されます。(本当は21が正しい)
これは、numberがない場合に文字列の”11″と10を足し合わせる処理になるためです。
numberをつけない場合の実例
numberをつけない場合は以下のようになります。
<body>
<div id="app">
<div>
<p>①number修飾子なし (type="number")</p>
<p>プロパティの状態:{{ figure1 }}</p>
入力:<input type="number" v-model="figure1">
<p>「+10」した値:{{figure1 + 10}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
var app = new Vue({
el:'#app',
data:{
//.number修飾子確認用
figure1: '',
}
})
▼ブラウザの表示
「+10した値」の横に表示されている値は初期状態では0 + 10のため「10」になっています。
↓ 数値の「11」を入力
数値の11を入力すると “11” + 10 が行われ、結果が「1110」になってしまっています。
numberがある場合の実例
v-modelにnumber修飾子をつけると、数値計算が正しく行われるようになります。
<body>
<div id="app">
<div>
<p>②number修飾子あり (type="number")</p>
<p>プロパティの状態:{{ figure2 }}</p>
入力:<input type="number" v-model.number="figure2">
<p>「+10」した値:{{figure2 + 10}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
var app = new Vue({
el:'#app',
data:{
//.number修飾子確認用
figure2: '',
}
})
▼ブラウザの表示
「+10した値」の横に表示されている値は初期状態では0 + 10のため「10」になっています。
↓ 数値の「11」を入力
数値計算が正しく行われ「21」が表示されています。
参考:type=”number”とtype=”text”の確認用コード
type=”number”とtype=”text”のインプットタグにおいて、numberの有り無しで数値計算がどのようになるかをまとめて確認するためのコードを載せておきます。
<body>
<div id="app">
<div>
<p>①number修飾子なし (type="number")</p>
<p>プロパティの状態:{{ figure1 }}</p>
入力:<input type="number" v-model="figure1">
<p>「+10」した値:{{figure1 + 10}}</p>
<br>
<p>②number修飾子あり (type="number")</p>
<p>プロパティの状態:{{ figure2 }}</p>
入力:<input type="number" v-model.number="figure2">
<p>「+10」した値:{{figure2 + 10}}</p>
<br>
<p>③number修飾子なし (type="text")</p>
<p>プロパティの状態:{{ figure1 }}</p>
入力:<input type="number" v-model="figure3">
<p>「+10」した値:{{figure3 + 10}}</p>
<br>
<p>④number修飾子あり (type="text)"</p>
<p>プロパティの状態:{{ figure3 }}</p>
入力:<input type="text" v-model.number="figure4">
<p>「+10」した値:{{figure4 + 10}}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.11"></script>
</body>
var app = new Vue({
el:'#app',
data:{
//.number修飾子確認用
figure1: '',
figure2: '',
figure3: '',
figure4: ''
}
})
▼ブラウザの表示