コンポーネントファイル
以下ファイルは、コンポーネントを記述しています。
my-inputコンポーネント(子コンポーネント)とvueインスタンス(親コンポーネント)です。
// my-inputコンポーネント(子コンポーネント)
Vue.component("my-input", {
props: ["val"],
template: `
<label>
名前:
<input type="text"
v-bind:value="val"
v-on:input="$emit('custominput', $event.target.value)"
/>
</label>
`,
});
// vueインスタンス(親コンポーネント)
new Vue({
el: "#app",
data: {
message: "",
},
});
コンポーネントを呼び出すhtmlファイル
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title></title>
</head>
<body>
<div id="app">
<!-- <my-input v-model="message"></my-input> -->
<!-- 上記v-modelは、以下と同等 -->
<my-input v-bind:val="message" v-on:custominput="message = $event"></my-input>
<p>入力値:{{message}}</p>
</div>
<!--ページ本体-->
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
<script src="js/index.js"></script>
</body>
</html>
v-modelは、上記コードのように、v-bindとv-onで表現できます。
v-modelをv-bindとv-onディレクティブを用いて説明してみます。
v-bind
コンポーネントのタグ(<my-input>)でのv-bindの対象は、そのコンポーネント(my-input)のプロパティになります。
今回の場合はvalプロパティになります。
v-bind:val=”message”は、valプロパティと親コンポーネント(vueインスタンス)のデータプロパティのmessageを紐づけている事を意味します。
v-on
v-on:custominputのv-onの対象のイベントcustominputは、index.jsのtemplate内に記述しているカスタムイベント$emit(‘custominput’, $event.target.value)です。
$emitは、子から親に値を渡すときに使用します。
第二引数は親コンポーネントに渡す値、今回の場合では、親コンポーネントのmessageプロパティに渡す値になります。
呼び出し側のv-on:custominput=”message = $event”は、カスタムイベントcustominputが発動した場合、その通知を受け取り親コンポーネントのmessageプロパティにイベント情報を渡します。
今回の場合は、コンポーネント側のinputタグ内にv-on:input=”$emit(‘custominput’, $event.target.value)”となっているので、inputフィールドに入力がされたら(inputイベント発動)カスタムイベントのcustominputが発動します。
発動後、呼び出し側では、v-on:custominput=”message = $event”となっているのでmessage = $eventが実行されます。
ここでの$eventは、カスタムイベントcustominputから渡された値$event.target.valueが格納されている事になります。
【追記】
呼び出し側でv-modelを使用した場合、カスタムイベント名は、custominputでは動作しない。
inputにしなければ動作しない。
本の説明では、「コンポーネント自体のinputイベント」と書いてあるので、ここはカスタムのイベントではなく、コンポーネント自体にinputイベントが備わっていると考えるのが良いのか・・・