Search code examples
javascriptcomponentsvue.js

VueJS - trigger child function


I'm new to using vuejs (2.0). I'm trying to get this functionality down:

  • Click a button
  • Trigger function in child component
  • Increment number in child's data

This is what I currently have

HTML:

<div id="root">
    <cart @addtocart="add()"></cart>
    <button @click="$emit('addtocart')">Add to Cart</button>
</div>

JS:

Vue.component('cart', {
  template: `<span>{{ items }}</span>`,
  data() {
    return {
      items: 0
    }
  },
  methods: {
    add() {
      alert('add');
    }
  }
});


new Vue({
  el: '#root',
  components: ['cart'],
});

Any help would be GREATLY appreciated. Thanks everyone!


Solution

  • You could use a centralized hub to emit events to (as suggested in the docs https://v2.vuejs.org/v2/guide/migration.html#dispatch-and-broadcast-replaced), then listen and react to those events inside your child components. Here's a quick update to your code that does that:

    var eventHub = new Vue();
    
    Vue.component('cart', {
      template: `<span>{{ items }}</span>`,
      data() {
        return {
          items: 0
        }
      },
      created() {
        eventHub.$on('add-item', this.add)
      },
      methods: {
        add() {
          alert('add');
          this.items++;
        }
      }
    });
    
    
    new Vue({
      el: '#root',
      components: ['cart'],
      methods: {
        addToCart() {
            eventHub.$emit('add-item')
        }
      }
    });
    

    I just started using vue myself so I may be wrong but as far as I know, having a child component depend on a specific parent is a bad idea as it forces the child component to be "coupled" to that parent to function and makes it not portable. Emitting events from a child component back up is fine though since that would just be the component letting anyone listening in know that something happened. I guess you could access the parent and the events it has emitted directly by using this.$parent.$on('add-item', this.method) but that looks hackish to me. Maybe if your root and child component will always be tightly coupled this way, this.$parent would be fine. The "instatiating a new vue instance" example above is probably just another way to do this without making tying your child component up to a parent component since Vue instances implement the event system (thus exposing $emit, $on methods)