【vue】 v-bindでvueの値をHTMLとやり取りする方法
vueでは、vueの値をHTMLの属性に設定したり、入力フォームに入れた値をvueの値に反映させるにはv-bind
やv-model
を用います。
v-bindは、やり取りというよりはvueからDOMへの一方向の押しつけ、v-modelは相互にやり取りできます。
目次
v-bindでvueの値をHTMLの属性に使う
要素の属性にv-bind:
をつけると、vueの値をタグの属性に設定することができます。
例えば、aタグのhref
に設定する場合、
Vue.createApp({ data() { protocol: "https://", domain: "example.com", } });
<!-- hrefにhttps://example.com が設定される --> <a v-bind:href="protocol + domain">...</a>
値を使う際にthis
は不要です。
のようになります。v-bind:
は単に:
と省略できるので、
<a :href="protocol + domain">...</a>
のように、:属性
と書くことができます。
See the Pen vue v-bind by Totori (@souki202) on CodePen.
ここで、中に入れるのは普通のJavascriptの式なので、文字列を入れる際はシングルクォーテーションで囲む必要があります。
<a :href="'https://' + domain">...</a> <!-- もちろん配列なども普通に使える --> <a :href="'https://' + domain[3]">...</a> <a :href="'https://example.com'"></a>
特に、上の例の3つ目のように文字列だけの場合、v-bind
を付けていることを忘れてシングルクォーテーション入れ忘れ、エラーとなったり動作しない場合があるので注意が必要です。 (v-bindしなければよいだけの話ですが…)
classとstyleの2つは特殊なため、別の場所で紹介します。
v-modelで入力値をvueとやり取り
v-modelを用いることで、HTML側のinputの値などとvueの値を相互にやり取りできます。
文字入力欄
v-model="変数"
のように書きます。
<input type="text" v-model="value"> <input type="date" v-model="foo.date">
const app = Vue.createApp({ data() { return { value: "foo", foo: { date: "2022-02-20", }, } }, });
とすると、1つ目の入力欄に文字列を入れると、vue側のvalue
という変数に、2つ目の入力欄に文字列を入れると、vue側のfoo.date
という変数に入力した値が格納されます。
何か同期ボタンのようなものはなく、入力すると自動的に同期されます。
さらに、vue側の値を更新すると、入力欄に入力されている値も更新されます。
See the Pen vue v-model by Totori (@souki202) on CodePen.
ラジオボタン
ラジオボタンの場合、一連の同じnameのラジオボタンには同じv-model
を入れます。
<input type="radio" name="r1" value="ボタン1" v-model="btnValue"> <input type="radio" name="r1" value="ボタン2" v-model="btnValue"> <input type="radio" name="r1" value="ボタン3" v-model="btnValue">
ラジオボタンは、一連のセットの中で1つしか選べません。そのため、同期先の変数も一つで良いです。
変数には、選択したボタンに設定されているvalue
属性の値が使われます。もちろん、value
はv-bind
していても問題ありません。
See the Pen vue v-model radio by Totori (@souki202) on CodePen.
もし最初からラジオボタンを選択した状態にしたい場合、vue側の変数に該当のvalue
を入れます。これは、変数に代入したときも反映されます。
const app = Vue.createApp({ data() { return { v: "ボタン2", // 上の例の2番目のラジオボタンを選択した状態になる } }, methods: { selectRadio() { this.v = "ボタン1"; // ボタン1が選択される } } });
チェックボックス(1つ)
1つのチェックボックスの場合、valueの設定に関係なくvueの変数にはtrueかfalseが入ります。
例えば、
<input type="checkbox" name="r1" value="ボタン1" v-model="v">
const app = Vue.createApp({ data() { return { : "", } }, });
というコードがあった場合、ボタンにチェックを入れてもv
に代入されるのはボタン1
ではなくtrue
です。
See the Pen vue v-model checkbox by Totori (@souki202) on CodePen.
ラジオボタンの時と同様に、
data() { return { v: true, } },
とすれば最初からチェックが入った状態になります。
この書き方は、チェックボックスが1つのときだけに可能な特殊な例と言えます。
vue側でv: []
のように配列にすれば、1個だけの場合でも下の複数パターンと同じ挙動にすることができます。
チェックボックス(複数)
複数のチェックボックスに対して同じv-model
を設定し、かつvue側でv-model
に入れる変数を配列とした場合、配列にはチェックが入った項目のvalue
が入ります。
例えば、
<input type="checkbox" value="ボタン1" v-model="v"> <input type="checkbox" value="ボタン2" v-model="v"> <input type="checkbox" value="ボタン3" v-model="v">
の3つのうち、2つ目と3つ目にチェックを入れると、vueには["ボタン2", "ボタン3"]
という値が入ります。
値は、チェックを入れると最後尾に入ります。ボタンの並び順ではありません。
See the Pen by Totori (@souki202) on CodePen.
今までと同様に、valueの値を設定すればチェックボックスにも反映されます。
const app = Vue.createApp({ data() { return { v: ["ボタン1", "ボタン3"], // ボタン1と3が選択された状態になる } }, });
セレクト
選択中のoptionの値が入ります。ここで、option
にvalue
が設定されていればvalue
が、設定されていなければ表示する値が利用されます。
v-model
はselect
タグ側に<select v-model="varname">...</select>
のように設定します。
例えば、
<select v-model="v"> <option value="hoge">aaa</option> <option>fuga</option> <option>foobar</option> </select>
の3項目だった場合、aaa
を選択時はhoge
が変数v
に入ります。fuga
を選択時はvalue
が無いため、表示する文字そのものであるfuga
が入ります。
See the Pen vue v-model select by Totori (@souki202) on CodePen.
セレクト(複数)
チェックボックスのときと同じように、vue側には配列を設定します。値は、普通のselect
と同じように、value
があればその値が、なければ表示する文字が値として入ります。
<select v-model="v"> <!-- ... --> </select>
const app = Vue.createApp({ data() { return { v: [], } }, });
See the Pen vue v-model select2 by Totori (@souki202) on CodePen.
select
で複数選択するには、タグ側にmultiple
属性を付けます。<select multiple></select>
選択時は、ドラッグする、Ctrlキーを押しながら選択する、で複数選択できます。
v-bindとv-modelをあわせる
例えば, ラジオボタンのvalueをv-bind
で、チェックが入ったらその値をv-model
に入れたい場合です。
この場合も今までの設定と同じです。ただvalue
が:value
になるだけです。
<input type="radio" name="r1" id="radio1" :value="radioValue1" v-model="v">
const app = Vue.createApp({ data() { return { radioValue1: "foobar", v: "", } }, });
このようにすると、input
のvalue
がfoobar
になるため、ラジオボタンを選択すると"foobar"
という値がv
に入ります。
See the Pen vue v-model radio2 by Totori (@souki202) on CodePen.
リストとv-model
配列を使ってv-for
を用いて入力欄を作成する時、普通のjsのようなfor-in
をしてしまうと、入力してもvueの変数に反映されません。代入された側の変数と元の変数に繋がりがないためです。
<!-- 駄目なパターン --> <div v-for="memo in memos"> <!-- v-forで新しく作った変数にv-modelを設定している --> <input type="text" v-model="memo"> </div>
そのため、インデックスを使用して元の変数にアクセスするべきです。
<!-- 良いパターン --> <div v-for="(memo, i) in memos"> <!-- vueにある変数にv-modelを指定している --> <input type="text" v-model="memos[i]"> </div>
修飾子で値のやりとりを制御
lazy
textやtextareaのinputで、inputイベントではなくchangeイベントが走ったときに適用されるようにできます。
<textarea v-model.lazy="v" cols="30" rows="10"></textarea>
これにより、v-model
に設定した値の更新回数が減少します。入力が完了したら通信してチェックするなど、更新時に重い処理をしたい場合に最適です。
number
input
でtype="number"
としても文字列がv-model
の変数に入りますが、これを自動的に数値に変換できます。
<input type="number" v-model.number="v">
つまり、元のままでは、100
を入力してもvueに"100"
が入ってしまうということです。
trim
文字列の最初と最後の空白を自動的に削除します。
<input type="text" v-model.trim="v">
v-bindとv-modelの違い
v-bindは、vueからDOMへの一方通行です。inputの値を変えてもvue側の値は変わりません。
v-modelは、双方に反映されます。vueの値を設定できますし、inputの入力を変えたりすればvue側の値も変わります。しかし、inputやselectのような入力欄系のものにしか使用できません。
まとめ
v-bindとv-modelは似ていますが、全く異なるものです。特に、inputに:value
としても、入力時にvue側に値が反映されないということに注意が必要です。
inputなどに入力した値との同期にはv-model
を、vueの値をタグの属性に設定したいならv-bind
と覚えておきましょう!
