親コンポーネントはpropsでデータを子コンポーネントに渡しますが、子コンポーネントがデータを返す場合は、カスタムイベントを使用する必要があります。
v-onを使用して、カスタムイベントをバインドできます。各Vueインスタンスは、イベントインターフェイス(Events interface)を実装します。
- $on(eventName)でイベントをリッスンします
- $emit(eventName)でイベントをトリガーします
さらに、親コンポーネントは子コンポーネントが使用されているところにv-onを直接使用して、子コンポーネントによってトリガーされたイベントをリッスンできます。
次の例では、子コンポーネントはその外部から完全に切り離されています。 親コンポーネントにある内部イベントをトリガーするだけです。
<div id="app">
<div id="counter-event-example">
<p>{{ total }}</p>
<button-counter v-on:increment="incrementTotal"></button-counter>
<button-counter v-on:increment="incrementTotal"></button-counter>
</div>
</div>
<script>
Vue.component('button-counter', {
template: '<button v-on:click="incrementHandler">{{ counter }}</button>',
data: function () {
return {
counter: 0
}
},
methods: {
incrementHandler: function () {
this.counter += 1
this.$emit('increment')
}
},
})
new Vue({
el: '#counter-event-example',
data: {
total: 0
},
methods: {
incrementTotal: function () {
this.total += 1
}
}
})
</script>
コンポーネントのルート要素でネイティブイベントをリッスンする場合、.nativeを使用してv-onを改善できます。 例えば:
<my-component v-on:click.native="doTheThing"></my-component>
dataは関数でなければなりません。
上記の例から見ると、button-counterコンポーネントのdataがオブジェクトではなく、関数です。
data: function () {
return {
count: 0
}
}
メリットは、各インスタンスが返されたオブジェクトの独立したコピーを維持できることです。dataがオブジェクトの場合、次の例が示すように、他のインスタンスが影響を受けます。
例
<div id="components-demo3" class="demo">
<button-counter2></button-counter2>
<button-counter2></button-counter2>
<button-counter2></button-counter2>
</div>
<script>
var buttonCounter2Data = {
count: 0
}
Vue.component('button-counter2', {
/*
data: function () {
// dataオプションは関数の場合、コンポーネントは相互に影響を与えない
return {
count: 0
}
},
*/
data: function () {
// dataがオブジェクトの場合、他のインスタンスが影響を受ける
return buttonCounter2Data
},
template: '<button v-on:click="count++"> {{ count }} 回にクリックされた。</button>'
})
new Vue({ el: '#components-demo3' })
</script>
カスタムコンポーネントのv-model
コンポーネントのv-modelは、デフォルトでvalueという名前のpropとinputという名前のイベントを使用します。
<input v-model="parentData">
は
<input
:value="parentData"
@input="parentData = $event.target.value"
>
と同じです。
次のカスタムコンポーネントrunoob-inputの例では、親コンポーネントのnumの初期値は100です。子コンポーネントの値を変更すると、親コンポーネントのnumをリアルタイムで更新できます。
例
<div id="app">
<runoob-input v-model="num"></runoob-input>
<p>入力された数値:{{num}}</p>
</div>
<script>
Vue.component('runoob-input', {
template: `
<p> <!-- inputという名前のイベントが含む -->
<input
ref="input"
:value="value"
@input="$emit('input', $event.target.value)"
>
</p>
`,
props: ['value'], // valueというprop
})
new Vue({
el: '#app',
data: {
num: 100,
}
})
</script>
v-modelはデフォルトでvalueを渡し、checkedではないため、単一のチェックボックスまたは複数のチェックボックスコンポーネントにmodelオプションを使用する必要があります。modelオプションは、現在のイベントのタイプと導入されたpropsを指定できます。
例
<div id="app">
<base-checkbox v-model="lovingVue"></base-checkbox>
<div v-show="lovingVue">
チェックボックスがオンの場合は表示する。
</div>
</div>
<script>
// 登録
Vue.component('base-checkbox', {
model: {
prop: 'checked',
event: 'change' // onchange イベント
},
props: {
checked: Boolean
},
template: `
<input
type="checkbox"
v-bind:checked="checked"
v-on:change="$emit('change', $event.target.checked)"
>
`
})
// ルートVueインスタンスを作成する
new Vue({
el: '#app',
data: {
lovingVue: true
}
})
</script>
この例では、lovingVueの値がcheckedのpropに渡され、changeイベントがによってトリガーされると、lovingVueの値も更新されます。
コメントを残す