Search code examples
vue.jsvuejs2vue-componentvuexvuex-modules

How can I call method in child component from parent component?


I have 4 component

My component first like this :

<template>
    ...
     <component-second></component-second>
    ...
</template>
<script>
    ...
    export default {
        ...
        updated() {
            // call check method in the component fourth
        }
    }
</script>

My component second like this :

<template>
    ...
     <component-third></component-third>
    ...
</template>
<script>
    ...
    export default {
        ...
    }
</script>

My component third like this :

<template>
    ...
     <component-fourth></component-fourth>
    ...
</template>
<script>
    ...
    export default {
        ...
    }
</script>

My component fourth like this :

<template>
    ...
</template>
<script>
    ...
    export default {
        ...
        methods: {
            check() {
                ...
            }
        }
    }
</script>

So, if update() in component first executed, I want to call check method in the component fourth

How can I do it?


Solution

  • You can use a Vue instance as event bus.

    You would create a global variable:

    var eventHub = new Vue(); // use a Vue instance as event hub
    

    To emit events you would use in any component:

    eventHub.$emit('myevent', 'some value');
    

    And, to listen to that event, again, in any component, do:

    eventHub.$on('myevent', (e) => {
        console.log('myevent received', e)
    });
    

    Demo:

    var eventHub = new Vue(); // use a Vue instance as event hub
    
    Vue.component('component-first', {
        template: "#component-first-tpl",
        data() { return {someFlag: true} },
        updated() {
          eventHub.$emit('myevent', 'some value');
        }
    });
    Vue.component('component-second', {
        template: "#component-second-tpl"
    });
    Vue.component('component-third', {
        template: "#component-third-tpl"
    });
    Vue.component('component-fourth', {
        template: "#component-fourth-tpl",
        created() {
          eventHub.$on('myevent', (e) => {
          	console.log('myevent received', e)
            this.check();
          });
        },
        methods: {
            check() {
                console.log('check called at fourth');
            }
        }
    })
    
    new Vue({
      el: '#app',
      data: {
        message: 'Hello Vue.js!'
      }
    })
    <script src="https://unpkg.com/vue"></script>
    
    <template id="component-first-tpl">
        <div>
            <component-second></component-second>
            
            <br>
            someFlag: {{ someFlag }}
            <button @click="someFlag = !someFlag">Trigger update</button>
        </div>
    </template>
    <template id="component-second-tpl">
        <div>
            <component-third></component-third>
        </div>
    </template>
    <template id="component-third-tpl">
        <div>
            <component-fourth></component-fourth>
        </div>
    </template>
    <template id="component-fourth-tpl">
        <div><h1>I'm Number 4</h1></div>
    </template>
    
    <div id="app">
      <p>{{ message }}</p>
      <component-first></component-first>
    </div>

    Note: If creating a dedicated instance as event hub is something complicated in your environment, you can replace eventHub with this.$root (inside your components) and use your own Vue instance as hub.