はじめに
仕事で使う事になったので1からVue.jsについて学んだ。
ちゃんと覚えておかないとまずそうな事を備忘録として1つ1つ残しておく。
親・子のコンポーネント間でv-modelを使う(双方向データバインディングする)
ソースコードとしては以下。
親・子 | SFC名 |
---|---|
親 | App.vue |
子 | EventTitle.vue |
<template>
<div class="container-sm">
<!-- 省略 -->
<div>
<h2>イベントのフォーム</h2>
<EventTitle
:value="eventData.title"
@input="eventData.title = $event"
></EventTitle>
<!-- <EventTitle v-model="eventData.title"></EventTitle> ←v-modelは上記のように書き換えられる -->
</div>
</div>
</template>
<script>
// 省略
import EventTitle from "./components/EventTitle.vue";
export default {
data() {
return {
// 省略
eventData: {
title: "",
},
};
},
components: {
// 省略
EventTitle,
},
// 省略
};
</script>
<template>
<div>
<p>タイトル</p>
<div class="form-floating mb-3">
<input
type="text"
class="form-control"
id="title"
placeholder="タイトル"
:value="value"
@input="$emit('input', $event.target.value)"
/>
<label for="title">タイトル</label>
</div>
<p>{{ value }}</p>
</div>
</template>
<script>
export default {
props: ["value"],
};
</script>
ソースコード全体は以下。
どのようにしてv-modelが動作する流れを詳細に見ていくと、、、(どこからスタートするかは鶏と卵であるが)
-
親コンポーネントの
:value
v-bind:value
の事であり、value属性を動的にバインド(value属性の値に設定する)するという事をする
最初は空文字なので空文字がバインドされる -
子コンポーネントの
props: ["value"]
親→子のコンポーネント間のデータ渡しの仕組みであるpropsを使い、親コンポーネントの属性名と同じ名前にする事で親コンポーネントの値を受け取る -
子コンポーネントの
:value="value"
propsで受け取った値をinputタグのvalue属性にv-bindでバインドする
これにより親コンポーネントで定義していたeventData.title
が子コンポーネントのinput要素に反映されるようになる -
子コンポーネントの
@input="$emit('input', $event.target.value)"
子→親のコンポーネント間のデータ渡しの仕組みである$emit()
を用いて、inputに入力があった際に親コンポーネントのカスタムイベントを発火させる
今回は親コンポーネントの@input
を発火させたいので第一引数がinput
になっており、$emitで副次的に渡せる値としてはinputに入力された値を渡したいので、第二引数が$event.target.value
になっている
※$event.target.value
の$event
はDOMに備わっているイベントオブジェクトで、今回はinput要素への入力で発火したイベントオブジェクトが格納される(子コンポーネントの@input
) -
親コンポーネントの
@input="eventData.title = $event"
子コンポーネントから$emit()で発火されたイベントが親コンポーネントで発火し、eventData.title
に$event($emitを使っている場合は$emitの第二引数に渡しているもの)
が代入される
これにより子コンポーネントの入力内容が親コンポーネントのオブジェクトに格納される
このような流れで、親・子のコンポーネント間でのv-modelは実現される。
※ソースコードの注意事項としては、
<EventTitle
:value="eventData.title"
@input="eventData.title = $event"
></EventTitle>
と
<EventTitle v-model="eventData.title"></EventTitle>
は全く同じもので、v-modelが:value="eventData.title"
・@input="eventData.title = $event"
というのを書かないでいいようにしてくれているだけ。
実際に内部的に動いているのは:value="eventData.title"
・@input="eventData.title = $event"
を書いた方なので、上記のような「v-modelが動作する流れ」になる。そのため、props: ["value"]
のvalue
をtestに書き換えて、v-bindの代入元のvalueもtestにしても動作しない。これは暗黙的に:value="eventData.title"
・@input="eventData.title = $event"
で処理されているから。
Vue.jsの勉強メモ一覧記事へのリンク
Vue.jsについて勉強した際に書いた勉強メモ記事のリンクを集約した記事。