Sergey Panfilov Sergey Panfilov - 1 month ago 86
Javascript Question

Communication between sibling components in VueJs 2.0

In vuejs 2.0

model.sync
will be deprecated.

So, what is a proper way to communicate between sibling components in vuejs 2.0?

As I catch the idea in Vue 2.0 is to have sibling communication by using a store or an event bus.

According to evan:


It's also worth mentioning "passing data between components" is
generally a bad idea, because in the end the data flow becomes
untrackable and very hard to debug.

If a piece of data needs to be shared by multiple components, prefer
global stores or Vuex.


[Link to discussion]

And:


.once
and
.sync
are deprecated. Props are now always one-way down. To
produce side effects in the parent scope, a component needs to
explicitly
emit
an event instead of relying on implicit binding.


(So, he suggest is to use
$emit
and
$on
)

I'm worried because of:


  • Each
    store
    and
    event
    has a global visibility (correct me if I'm wrong);

  • It's to much to create a new store for each minor communication;



What I want is to scope somehow
events
or
stores
visibility for siblings components. Or perhaps I didn't catch the idea.

So, how communicate in a right way?

Answer

Okay, we can communicate between siblings via parent using v-on events.

Parent
 |-List of items //sibling 1 - "List"
 |-Details of selected item //sibling 2 - "Details"

Let's assume that we want update Details component when we click some element in List.


in Parent:

Template:

<list v-model="listModel"
      v-on:select-item="setSelectedItem" 
></list> 
<details v-model="selectedModel"></details>

Here:

  • v-on:select-item it's an event, that will be called in List component (see below);
  • setSelectedItem it's a Parent's method to update selectedModel;

JS:

//...
data () {
  return {
    listModel: ['a', 'b']
    selectedModel: null
  }
},
methods: {
  setSelectedItem (item) {
    this.selectedModel = item //here we change the Detail's model
  },
}
//...

In List:

Template:

<ul>
  <li v-for="i in list" 
      :value="i"
      @click="select(i, $event)">
        <span v-text="i"></span>
  </li>
</ul>

JS:

//...
data () {
  return {
    selected: null
  }
},
props: {
  list: {
    type: Array,
    required: true
  }
},
methods: {
  select (item) {
    this.selected = item
    this.$emit('select-item', item) // here we call the event we waiting for in "Parent"
  },
}
//...

Here:

  • this.$emit('select-item', item) will send item via select-item directly in parent. And parent will send it to the Details view
Comments