vue2.07 Communication Between Sibling Components
はじめに。
vue2から$dispatchが非推奨となりコンポーネント間の通信仕様に変更があったようで実装してみた。
と言うより本格的なvueの使用は2からだったのでむしろ良かったのかもしれない。
当初、コンポーネント間のメソッドの呼び出しは自由に出来るものと思っていたが甘かった。
公式サイトの
全てのコンポーネントや Vue インスタンスは自身のライフサイクルを持ちます や
全ての Vue.js コンポーネントはそれ独自のスコープを持つ個々の Vue インスタンスです。それはコンポーネントを使用する時にスコープがどのように機能するか理解することが大事です。
を読み飛ばしていた。
比較的親子間の通信はやっている方が多かったのだが
親子関係を持たないコンポーネント間の通信に関するページが少なく
"Communication Sibling Components vue"
で検索してやっと解決方法のヒントに出会ったのでメモ書き。
"Sibling"がキーワード。親子でなく兄弟(対等な)関係
やりたかった事
1.コンポーネントAから渡されたパラメータをコンポーネントBで取得しtemplate内のタグにバインド
2.コンポーネントBのメソッドをコンポーネントAでキック
実装方針
http://012-jp.vuejs.org/guide/components.html
にあるように基本的に$$emit + $onを使用して実装可能だが
下準備が必要。公式サイトにそれっぽいことが載ってなかった。
実装
app.js
公式サイトが不親切でフロントエンドに詳しくない私にとって
ES5 or ES6 or plain Jsの違いもわからない状態からではちょと厳しかった。
以下のように
ダミーオブジェクトのようなもの(eventHub)を用意してexportの必要があった。
ソースが汚くてすみません。大事なのは※部分。
var eventHub = new Vue();
module.exports = eventHub;//←※これだとok
//exports.eventHub = eventHub; ←これはngだった
var vue = new Vue({
el: '#app',
data:{
itemList: null,
outline : null
},
created: function () {
// initialize
},
components: {
ArticleGrid: require('./template/com1.vue'), //呼び出す側のコンポーネント
ArticleDetail: require('./template/com2.vue'),//呼び出さるメソッドを保持
}
})
com1.vue
呼び出す方のコンポーネント
setDetailという名前で呼び出す。($emit)
直接呼び出すのではなくapp.jsのeventHub経由で呼び出しています。
<template>
<a class="grid__item" v-on:click="showDetail">
...
</a>
</template>
<script>
// ※ここでimportが必要
// 海外サイトでこれがないために動いてないソースも多かった。
import eventHub from '../app'
export default {
props: ['abc'],
methods: {
showDetail: function () {
// ※第2引数にパラメータを渡せる⇒これでコンポネント間の値の受け渡しも可能
eventHub.$emit('setDetail', tmpoutline)
console.log("dispatch--");
}
},
}
</script>
com2.vue
呼び出される方のコンポーネント
setDetailという名前で登録。($on)
<template>
<article class="content__item">
...
</article>
</template>
<script>
import eventHub from '../vueTop'
export default {
created: function () {
// ※メソッドの登録。実際に呼ばれるのは以下のmethods内
eventHub.$on('setDetail', this.setDetail)
},
methods: {
setDetail: function (param) {
console.log("--called");
}
}
}
</script>