かなり時間取られたので、記事のネタにして精神の安定を図ります。ちなみに私は「返り値」派ですが、「戻り値」の方が若干多数派っぽい?ですね。
やりたかった事
「layouts/header.vue」の?ボタンを押すと、「pages/hoge.vue」や「pages/poyo.vue」のmethods: generateHelp()
を叩いて、その戻り値を「layouts/header.vue」に渡してダイアログに表示する、みたいなことをしたかった。methods: generateHelp()
の無い「pages/huga.vue」については、何も起きないなりundefinedが返ってくるなり適当でいいやと。
そもそもこの設計自体が間違ってる気がしないでもないです。何か良い案ございましたらご教示ください。
実現した方法
- ?ボタンを押すと'requireHelp'イベントを発火させる
- 「pages/hoge.vue」は'requireHelp'イベントを検知して、
methods: generateHelp()
を叩く -
methods: generateHelp()
は処理の最後に、自身の戻り値を引数として'returnHelp'イベントを発火させる - 「layouts/header.vue」は'returnHelp'イベントを検知して、引数をダイアログに表示させる
<template>
<h1>たいとる</h1>
<button @click="clickHelpButton">?</button>
<nuxt />
</template>
<script>
export default {
// 'returnHelp'イベントの検知(4の前半)
created () {
this.$nuxt.$on('returnHelp', (help) => {
this.showDialog(help)
})
},
// ページを離れる際に検知を終了
// (書かないとどういった問題が起きるのか、誰か教えてください><)
beforeDestroy () {
this.$nuxt.$off('returnHelp')
},
methods: {
// ボタンクリック時に各pagesへ向けて'requireHelp'イベント発火(1)
clickHelpButton () {
this.$nuxt.$emit('requireHelp')
},
// ダイアログを表示(4の後半)
showDialog (help) {
/* ダイアログを表示する処理 */
}
}
</script>
<script>
export default {
// 'requireHelp'イベントの検知(2の前半)
created () {
this.$nuxt.$on('requireHelp', () => {
this.generateHelp()
})
},
// ページを離れる際に検知を終了
beforeDestroy () {
this.$nuxt.$off('requireHelp')
},
methods: {
// ?ボタンが叩きたかったお目当ての関数(2の後半)
generateHelp () {
// なんかヘルプ内容を生成
const help = 'ggrks'
// layouts/header.vueに向けて'returnHelp'イベントを発火(3)
this.$nuxt.$emit('returnHelp', help)
return help
}
}
</script>
うまくいかなかった方法
$refs
を使う
「親コンポーネントから子コンポーネントのmethodsを触る方法」みたいな記事を参考にして、<nuxt ref="page" />
としてthis.$refs.page.generateHelp()
ってすれば直接叩けないかと思ったけど、駄目。this.$refs.page
が参照するのはnuxt自体(?)で、各pagesではない???(どう表現するのが正解なのか分かってない)
Vuex storeを経由する
ボタンを押したときにstoreを更新させようと思ったら、結局イベント発火が必要なのに気づいてやめた。layoutsからpages内の子コンポーネントのmethodsを……ってなったらstore経由した方が楽かもしれないが、そもそもその設計を見直した方が良さそう。
参考文献
[Nuxt.js] EventBusを使ってコンポーネント間で通信する
【Vue.js】親コンポーネントから子コンポーネントのメソッドを叩く
繰り返しになりますが、もっとこうしたらスマートだよ!って方法あれば教えてください。切に。