基礎からメモ: Vue.js CH5-p166 親から子のイベントやメソッドを使う
$refs
を使って、親から子のメソッドを使ったり、イベントを発火させたりできる。
子コンポーネントで$on
を使って自分のイベントをハンドルできるようにしておく。特定のカスタムイベント名で子のメソッドを呼び出すことも可能。
<div id="app"> <my-component></my-component> </div>
コンソール出力するだけのopen
イベントと、自分のmessageCall
メソッドを呼び出すcall
イベントを定義。
Vue.component('comp-child', { template: '<div>Child Component</div>', created: function () { // 子コンポーネントのイベント this.$on('open', function () { console.log('子コンポーネントのイベントを発火!') }); this.$on('call', function () { this.messageCall(); }); }, methods: { messageCall: function() { alert("子コンポーネントのメソッドを起動!"); } } })
親コンポーネントの2つのボタンをクリックすると、それぞれに対応した子のイベントが発火し、子の方で定義された動作が発生する仕組み。
let myComponent = { template: `<div class="parent"> <comp-child ref="child"></comp-child> <button v-on:click="handleClick">Child Event Fire!</button> <button v-on:click="callChildMeth">Call Child Method!</button> </div>`, methods: { handleClick: function() { // 子コンポーネントのイベントを発火 this.$refs.child.$emit('open'); }, callChildMeth: function() { // 子コンポーネントのメソッドを呼ぶ this.$refs.child.$emit('call'); } } }; var app = new Vue({ el: '#app', components: { 'my-component': myComponent } });
ただ子コンポーネントのメソッドを直接起動させたいなら、$emit
によるイベント処理を介さずに、親のメソッドを次のように書いても動作する。
callChildMeth: function() { // 子コンポーネントのメソッドを直接呼ぶ this.$refs.child.messageCall(); }
こちらのほうがシンプル。
子のメソッドの引数を受け取る
親コンポーネントの中で使われている子コンポーネントのカスタムタグの属性値にあたる部分は、親のスコープになる。一見、子側のメソッドに渡された引数などを受け取れないように見えるが、その子側のメソッド内で$emit
が実行されている場合、その引数を$event
変数で参照できる。
$event
変数には$emit
の第一引数しか格納されていないため、複数の値を渡したい場合は1つのオブジェクトにまとめる。子のカスタムタグで呼び出す親メソッドの引数には$event
の後に、文字列や親のデータなどを第二引数以降として渡すことができる。
<div id="app"> <my-component></my-component> </div>
/* 親子関係のコンポーネント $emit の引数を親のメソッドへ渡す。 */ Vue.component('comp-child', { template: `<div>{{ val }} <button v-on:click="callMeth">呼び出し!</button></div>`, props: ["val"], methods: { callMeth: function() { this.$emit('childs-event', { id: 1, name: "新しい名前"}) } } }); let myComponent = { template: `<div> <comp-child v-on:childs-event="parentsMethod($event, p_message)" class='parent' v-bind:val="p_message"></comp-child> </div>`, data: function() { return { p_message: '親のデータ' } }, methods: { parentsMethod: function(c_event, p_data) { console.log(c_event.id, c_event.name, p_data); } }, }; let app = new Vue({ el: '#app', components: { 'my-component': myComponent } });
子コンポーネントのテンプレートにあるボタンを押したときのコンソール表示は
1 "新しい名前" "親のデータ"