v-modelについてv-on・v-bindとの違いと使い方

2178 回閲覧されました
みなさんこんにちは、jonioです。
今回はv-modelディレクティブの使い方をすぐ忘れる自分へのアウトプットの記事です。
v-modelディレクティブはv-bindディレクティブとv-onディレクティブを合わせた物ですが違いを見るためにv-onディレクティブとv-bindディレクティブの解説をまずします。
vueのバージョン2で解説していますが考え方はバージョン3でも同じです。
v-bindディレクティブ
コードを下記にします。
<!DOCTYPE html>
<html lang="ja">
<head>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<title>Vue.jsのデモ</title>
</head>
<body>
<div id="app">
<input type="text" v-bind:value="content">
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
content:"v-bindディレクティブ"
},
});
</script>
</body>
</html>
これで下記の表示になります。

v-bindディレクティブは17行目の「content:”〜”」の〜が9行目のcontentに入り17行目のcontent:”〜”の〜から一方的に9行目のcontentを決定します。
「17行目のcontent」→「9行目のcontent」の流れです。
もっと言うとscriptタグのデータから値を設定しています。
他の例で考えます。
他の使用例
下記のコードで考えます。
<table>
<thead>
<tr>
<th>日付</th>
<th>最高値</th>
<th>最安値</th>
<th>編集</th>
</tr>
</thead>
<tbody>
<tr v-for="item in editDatas" :key="item.id">
<td>{{ item.date }}</td>
<td>{{ item.high_value }}</td>
<td>{{ item.row_value }}</td>
<td>
<a :href="`/admin/edit/${item.id}`">編集</a>
</td>
</tr>
</tbody>
</table>
<script setup>
import { ref, onMounted } from 'vue';
import axios from 'axios';
const editDatas = ref([]);
const csrf = document.querySelector('meta[name="csrf-token"]').getAttribute('content');
onMounted(async () => {
const response = await axios.get('/api/value-data');
editDatas.value = response.data;
})
</script>
26行目の「editDatas」の値を31行目で設定して11行目〜18行目で使っています。
16行目にv-bindを使っています。
「v-bind」は「:」と書いても同じです。
編集なので「${item.id}」を動的にしないといけませんがこんな使い方もできます。
この場合もscriptタグのデータから値を設定していると言えます。
次はv-onディクティブです。
v-onディレクティブ
コードを下記にします。
<!DOCTYPE html>
<html lang="ja">
<head>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<title>Vue.jsのデモ</title>
</head>
<body>
<div id="app">
<input type="text" v-on:input="vOn">
{{text}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
text:""
},
methods:{
vOn(e){
this.text = e.target.value;
}
}
});
</script>
</body>
</html>
これで下記になります。
9行目の「vOn」の中身を22行目〜24行目で決めていますがinputタグの中に文字を書くことで9行目のvOnが作動してinputタグの中に書いた内容が10行目の「text」に表示されます。
このようにv-onディレクティブは9行目の「vOn」→23行目の「this.text = e.target.value」の一方通行です。
次はv-modelディレクティブです。
v-modelディレクティブ
コードを下記にします。
<!DOCTYPE html>
<html lang="ja">
<head>
<link rel="stylesheet" type="text/css" href="css/reset.css">
<title>Vue.jsのデモ</title>
</head>
<body>
<div id="app">
<input type="text" v-model="vModel">
{{vModel}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
<script>
new Vue({
el: '#app',
data: {
vModel:"v-modelディレクティブ"
},
});
</script>
</body>
</html>
これで下記になります。
v-onディレクティブの時と似ていると思いますが少し違います。
v-onディレクティブの時はinputタグの中に文字を書いていくと{{text}}の中に書いた文字が表示されていきました(vOn→text)が今回はinputタグの中の文字が最初から{{vModel}}に表示されています。
つまりinputタグの中の文字が最初から{{vModel}}に表示されるので「19行目のvModel」→「9行目のvModel」(v-bindディレクティブ)ができます。
また、inputタグの中の文字を変えると{{vModel}}の中の文字も変わるので「9行目のvModel」→「19行目のvModel」(v-onディレクティブ)ができるのでv-modelディレクティブはv-onディレクティブとv-bindディレクティブを合わせたものということができます。
だから「v-modelディレクティブ = v-onディレクティブ+v-bindディレクティブ」と認識しましょう。
やってはいけない書き方
v-modelディレクティブはv-onディレクティブとv-bindディレクティブを併せた物なので下記の書き方でも動きますが意味がないです。
<div id="app">
<input
type="text"
v-bind:value="content"
v-on:input="vOn"
>
</div>
こんな時はv-modelがあるのでそれを使いましょう。