$emit and $ON can communicate globally across components. Why not use vuex? This question begins with the origins of the EVENTbu event bus S and VUEX. (while the larger vue3.0 is still on the way, let’s make some fresh rice.)

Component communication

A long, long time ago, in the kingdom of Vue there was A component tower, there was A component family, A,B,C, A component father A and son B,C lived between different levels, they were very far apart.

Father – > the son

At this time, the father missed his son, wanted to send him a letter, what to do? Simple! On each child component there is a props “mailbox” through which the father can deliver mail directly.

    Vue.component('blog-post', {// In JavaScript is the props of camelCase: ['postTitle'],
      template: '<h3>{{ postTitle }}</h3>'}) <! -- kebab-case in HTML --> <blog-post post-title="I am father's message!></blog-post>
Copy the code

Children – > father

B and C were very happy when they received their father’s letter. Then the vue.$emit messenger came out and the sub-component used vue.$emit to send a message to the upper level.

this.$emit("todo",{
    res:"This is news from my son."
})
Copy the code

After receiving the news, the father has to respond to different types of information from the son

    this.$on('todo'.function(data){// todo //data => message from son})Copy the code

brother

A often tells B and C to keep in touch with each other. However, $emit can only send messages to the upper level. How can the two brothers who live on the same floor communicate with each other?

Eventbu Indicates the event bus

At that time, a wise man came up with a solution. Since you all use the $emit method, why don’t I open sf Express directly? Then the vue eventBus comes out and constructs a bus using a VUE instance floating outside the component tower. The son’s message is emitted to the bus via $emit.

B.$root.bus.$emit('todo')
Copy the code

The father gets the message from the bus and sets the response event

A.$root.bus.on('todo'.function() {})Copy the code

So fathers and sons can easily communicate with each other and the big question is, how do brothers communicate with each other? At this time, the wise man of bus jumped out and said, customer is God, no matter father or son can use sf Express bus, so as to realize the communication between brother components

B.$root.bus.$emit('todo'// Brother C can also receive this message.$root.bus.on('todo'.function() {})Copy the code

problem?

At this point, back to the point of this article, why are we using Vuex when eventBus is so good? In the beginning, our project might be as simple as this

1. Code logic deteriorates and readability deteriorates. 2. An on(or Dispatch) event is required for each action parent. You'll have a hard time figuring out where every event is triggered, all business logic, rightCopy the code

Simple example

Let’s take a simple example. Your company has a display component that displays the current value of increment in the App root component. You hire two new employees and assign them two tasks.

  1. Add INCREMENT once by clicking on it and display the current increment number within the component. Increment this counter is subscribed to increment, and clicking on the counter successfully causes display and childDisplay to display increment by 1. Little A happily and quickly completed the task commit and then push
  2. I need a button component that emits a reset event to the app instance. This event will reset increment 0 on the app. Ok, B is happy to commit and push
  3. Increment = 0; increment = 0;} Increment = 0; increment = 0; However, as little B did not know that component A also subscribed to the data of INCREMENT, the status of component A was not updated.

vuex

In order to prevent these problems, it is at this time that King Youxiaorighto steps in, and he uses the ideas of the Flux kingdom next door to lead the wise men of the country to work out a new way to solve this confusing problem. That’s the Vuex.

By definition

  1. A store is a repository that holds data for a project (store.state)
  2. (Strict mode) To solve the problem of not being able to track state changes, the data in the warehouse is not changed directly by modifying store.state, but by committing an action that tells the warehouse, [vuex] Do not mutate vuex store state outside mutation handlers
  3. After receiving the commit action, the repository will look for the corresponding event in store.mutation and change store.state

Let’s go back to the simple example

Solution 1(Simple Store mode)

To address these issues, we made several interesting changes. (state)

  1. We define a constant store in store
  2. A variable called sharedState is defined in the local data, which is a mapping in store.state
  3. Since sharedState is vue’s data, it makes Store. state a responsive data, and vue automatically updates the sharedState data when store.state changes.

The increment subscribed by COMPONENT A and component B is no longer the data in the root component, but the data in the warehouse. When the warehouse data changes, VUE will automatically update each component subscribed to INCREMENT data.

<template> Count is {{sharedstate. counter}} </template> <script> import store from'.. /store'

export default {
  data () {
    return {
      sharedState: store.state
    }
  }
}
</script>
Copy the code
// This is A component import store from'.. /store'
<template>
  Count is {{ sharedState.counter }}
</template>
export default {
  data () {
    return {
      sharedState: store.state
    }
  },
  methods: {
    activate () {
      this.sharedState.counter += 1
    }
  }
}
Copy the code
// This is component B import store from'.. /store'
export default {
  data () {
    return {
      sharedState: store.state
    }
  },
  methods: {
    reset () {
      this.sharedState.counter = 0
    }
  }
}
Copy the code
Scheme 1 Deformation

Is this the best way? Imagine A and B leaving the company after they developed countless reset and counter components. You say to C, I want all the increments not to exceed 100. Does C want to refactor all the components to determine the size? This is a ridiculous choice. This is where we introduce a new approach. (mutation)

var store = {
  state: {
    counter: 0
  },
  increment: function () {
    if (store.state.counter < 100) {
      store.state.counter += 1;
    }
  },
  reset: function() { store.state.counter = 0; }}export default store
Copy the code

From this derivation, the Vuex took shape

import Vuex from 'vuex'
import Vue from 'vue'

Vue.use(Vuex)

var store = new Vuex.Store({
  state: {
    counter: 0
  },
  mutations: {
    INCREMENT (state) {
      state.counter ++
    }
  }
})

export default store
Copy the code

So let’s see what’s going on here

  1. We introduced a Vuex module and activated it as a VUE plug-in
  2. Our repository store is no longer a generic jsonObject but an instance of vuex.store
  3. Mutation was used to change the state

why better ?

  1. If we keep a copy of all the states during development, we can debug the code like Super Hero and time travel, recording every state change
  2. You can build middleware, such as a log printer, that logs every time a user submits an action, making it easier to debug and fix bugs when problems occur
  3. Forcing you to manage all your actions through a single store makes team development easier and clearer

conclusion

We can draw the conclusion of this paper through a long analysis.

  1. Vuex is officially launched, event bus is a master in the folk
  2. For larger applications, Vuex is a better solution than EventBus
  3. Vuex is easier to debug and manage
  4. Vuex is not the best solution. In some small applications, you may have only a small amount of data interaction, or even a login state store, where an event bus or simple state management is recommended. Last but not least, vuex smells good. Ps: This is just my opinion. If you have any questions, please feel free to correct them. 😘