title: Communication between components in vuejs
body: <p>I know, that communication between components in Vuejs >= 2.0 is done by three concepts</p>
  
  <ol>
  <li><strong>props</strong> - is how outer context can pass data to the component,</li>
  <li><strong>events</strong> - is how component lets know outer context about changes,</li>
  <li><strong>slots</strong> - this one is not important for my question.</li>
  </ol>
  
  <p>I am also aware of central state pattern and all that stuff around it. But sometimes is common to be able to tell to child component "do something, what changes your <strong>internal state</strong>".</p>
  
  <p>Here are some scenarios:</p>
  
  <ol>
  <li>TreeView (recursive component) and "collapse all" button - you need to tell all child components to collapse. I know, here is applicable central state pattern, but let's imagine that state of the node (expanded/collapsed) is part of component's internal state.</li>
  <li>Counters - i can have multiple counters on the page a parent component have button "increment all" - again, I need to "call" increment method on each child component.</li>
  </ol>
  
  <p>Question is: how to achieve "event based" communication between components in parent -> children direction. I feel that it's kinda common scenario.</p>
  
  <p>I made an example jsbin. However, I'm not sure it doesn't violate some fundamental ideas of vue js.</p>
  
  <p><a href="https://jsbin.com/kakucuf/edit?html,js,output" rel="nofollow noreferrer">https://jsbin.com/kakucuf/edit?html,js,output</a></p>
  
  <pre><code>const Foo = {
    name: 'Foo',
    template: '#a-template',
    props: {
      name: {
        required: true,
        type: String
      },
    },
    data() {
      return {
        counter: 0
      }
    },
    mounted() {
      this.$on('increment', this.increment);
    },
  
    methods: {
      increment() {
        this.counter += 1;
      }
    }
  }
  
  new Vue({
      el: "#app",
    components: {
      foo: Foo,
    },
    methods: {
      incrementAll() {
        this.$children.forEach((child) =&gt; child.$emit('increment'));
      }
    }
  });
  </code></pre>