Help us understand the problem. What is going on with this article?

vue-routerで親子間でのイベント処理

概要

vue-router使用時の「子→親」あるいは「子1→子2」のイベント渡しの記述方法について自分用メモ

:warning:ソースコードは簡略化したもので、ちゃんとテストしていないので動かないかも

サンプルコード

this.$router.app.$on を扱うのがポイント。それ以外は通常のイベントバスのやり方と同じ。

主要な部分

app.js
//(前略)
const app = new Vue({
    router, // これが「ルーターインスタンスを root インスタンスに router オプションとして」かな?
    el: '#app',
    render: h => h(App)
});

親コンポーネント

parent.vue
<template>
    <div>  
        <child1></child1>
        <child2></child2>
    </div>
</template>

<script>
// 子2つを配置するのみ
import component_child1 from './child1.vue'
import component_child2 from './child2.vue'

export default {
    components: {
      'child1': component_child1,
      'child2': component_child2
    }
};
</script>

子コンポーネント(2つ)

目標とする動作は下記。

  1. child1でボタンを押すと test_method_child1 が実行される。
  2. test_method_child1 内で test_event_global がスローされ、child1は非表示。
  3. child2でイベントの解除(重要、後述。参考資料を参照。)
  4. child2ではイベントを test_event_globaltest_event_child2 としておく。
  5. child2でイベントを受け取ったら、v-on:test_event_child2test_method_child2 が実行。
  6. child2が表示され、Hello Worldが見える。
child1.vue
<template>
    <div v-show="visible_child1">
       <button v-on:click="test_method_child1">Run Test</button>
    </div>
</template>

<script>
export default {
    data() {
        return {
            visible_child1 : true  // 表示/非表示制御
        };
    },
    methods: {
        test_method_child1() {
            this.visible_child1 = false;
            // イベントバスを this.$router.app として、イベントをスロー
            this.$router.app.$emit('test_event_global');
        }
    }
}
</script>
child2.vue
<template>
    <div v-on:test_event_child2="test_method_child2" v-show="visible_child2">
       Hello world !!
    </div>
</template>

<script>
export default {
    data() {
        return {
            visible_child2 : false // 表示/非表示制御
        };
    },
    mounted() {
        // イベントバスを this.$router.app として、コンポーネントのイベントに紐づけている
        this.$router.app.$off('test_event_global');
        this.$router.app.$on('test_event_global', this.test_event_child2);
    },
    methods: {
        test_method_child2() {
            this.visible_child2 = true;
        }
    }
}
</script>

注意点

解除が行われない、というより .$off をしないと蓄積するようです

ページ遷移してcreatedやmountedが何度も呼ばれると、そのたびに蓄積されてしまうらしい。
( beforeDestroyかdestroyedの中で解除すればいいのかな )


上記は例。$onでメソッドを直接叩くこともできるはず。
表示/非表示みたいなことを実現するだけならv-onは取ってしまって

child2.vue
<div v-show="visible_child2">
(中略)
this.$router.app.$on('test_event_global', this.test_method_child2);

とすることも。

参考資料

  1. Vue Router / API リファレンス
  2. Vue.js のグローバルイベントバスでの親子間以外の通信と vue-router
t_mitarai
地獄から甦ったサーバーサイド開発忍者 ソースコードの半角スペースを空文字に置換し、 ランダムな位置に全角スペースを埋め込むのを生業にしている
nightley-inc
人や物の位置や動きのデータを解析し、価値ある情報をクライアントへ届ける位置情報プラットフォームを開発・運営しているスタートアップです。
https://nightley.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした