6
Author: Anthony Gore
Translator: Frontend Xiaozhi
Source: vuejsdevelopers
There are dreams and dry goods. search 160aee812f375d [Moving to the World] Follow this brushing wisdom who is still doing dishes in the early morning.

This article GitHub https://github.com/qq449245884/xiaozhi has been included, the first-line big factory interview complete test sites, materials and my series of articles.

Vuex is an essential tool in the Vue.js ecosystem. But developers who are new to Vuex may be repelled by terms such as "state management mode" and confused about what they actually need Vuex for.

This article can be regarded as an introduction to Vuex, and of course it will also provide advanced concepts of Vuex and show you how to use Vuex in your application.

Problems solved by Vuex

To understand Vuex, we must first understand the problem it solves.

Suppose we have developed a multi-user chat application. The interface has a user list, a private chat window, an inbox with chat history, and a notification bar to notify the user of unread messages of other users that are not currently viewed.

Millions of users chat with millions of other users through our app every day. However, someone complained about an annoying problem: the notification bar occasionally gave wrong notifications. The user is notified that there is a new unread message, but when they view it, it is just a message that has already been read.

What the author describes is the real situation that Facebook developers encountered in their chat system a few years ago. In the process of solving this problem, the developers created an application architecture "Flux" Flux forms the basis of Vuex, Redux and other similar libraries.

Flux

Facebook developers struggled with the "zombie notification" issue for some time. They finally realized that its persistence was not just a simple flaw-it pointed out some potential flaws in the application architecture.

This defect is easiest to understand in abstraction: when there are multiple components that share data in an application, the complexity of their interconnection will increase to the point where it is impossible to predict or understand the state of the data. Therefore, the application cannot be extended or maintained.

Flux is a pattern, not a library. We cannot go to Github to download Flux. It is a design pattern similar to MVC. Libraries like Vuex and Redux implement the Flux pattern in the same way as other frameworks implement the MVC pattern.

In fact, Vuex does not implement all of Flux, just a subset. But don't worry about this problem for now, we focus on understanding the key principles it follows.

Principle 1: Single source

The component may have local data that only needs to be known. For example, the position of the scroll bar in the user list component may not be related to other components.

However, any data to be shared between components (ie application data) must be kept in a separate location, separate from the components that use it.

This single location is called "store". The component must read the application data from this location and cannot keep its own copy to prevent conflicts or disagreements.

import { createStore } from "vuex";

// Instantiate our Vuex store
const store = createStore({

  // "State" 组件的应用程序数据
  
  state () {
    return {
      myValue: 0
    };
  }
});

// 组件从其计算的属性访问 state 
const MyComponent = {   
  template: "<div>{{ myValue }}</div>",
  computed: {
    myValue () {
      return store.state.myValue;
    }   
  } 
};

Principle 2: Data is read-only

The component can read data freely store But store cannot be changed, at least not directly.

Instead, they must inform store their intention to change the data. store is responsible for making changes through a set of defined functions (called mutation

Why use this method? If we centralize the data change logic, then in the case of inconsistent states, we only need to check in the same place instead of each specific file. We minimize the possibility of some random components (possibly in third-party modules) changing data in unexpected ways.

const store = createStore({ 
  state() { 
    return {
      myValue: 0
    };
  }, 
  mutations: { 
    increment (state, value) { 
      state.myValue += value;
    }
  } 
});
// 需要更新值吗?
// 错误的,不要直接更改 store 值
store.myValue += 10;
// 正确的,调用正确的 mutations。
store.commit('increment', 10);

Principle 3: The mutation is synchronous

If the application implements the above two principles in its architecture, it is much easier to debug data inconsistencies. You can record the submission and observe how the status changes (it is indeed possible to do this when using Vue Devtools).

But if our mutation is called asynchronously, this ability will be weakened. We know the order of submission, but we don't know the order in which the components are submitted.

Synchronizing mutation ensures that the state does not depend on the sequence and timing of unpredictable events.

That's cool, so what exactly is Vuex?

With all this background knowledge, we can finally solve this problem-Vuex is a library that helps us implement Flux architecture in Vue applications. By implementing the above principles, even when data is shared between multiple components, Vuex can still keep our application data in a transparent and predictable state.

Now that we have an advanced understanding of Vuex, let's take a look at how to create Vuex-based applications in actual projects.

Make a to-do-list using Vuex

To demonstrate the use of Vuex, we set up a simple to-do application. You can access a valid example of the code here

Example address: https://codesandbox.io/s/happy-williams-rdni7

If you try a wave on your own computer, you can use the following command:

vue create vuex-example

Install Vuex

cd vuex-example
npm i -S vuex@4
npm run serve

Create a Vuex store

Now, create Vuex store, created in the project src/store/index.js :

mkdir src/store
touch src/store/index.js

Open the file and import the createStore method. This method is used to define store and its characteristics. Now, we export the store so that it can be accessed in the Vue application.

// src/store/index.js

import { createStore } from "vuex";

export default createStore({});

Add store to Vue instance

In order to be able to access the Vuex store from any component, we need to import the store module store as a plugin on the main Vue instance

// src/main.js

import { createApp } from "vue";
import App from "@/App";
import store from "@/store";

const app = createApp(App);

app.use(store);

app.mount("#app");

Create a simple application

As mentioned above, the focus of Vuex is usually to create scalable global state in large applications. However, we can demonstrate its functionality in a simple to-do application.

The effect after completion is as follows:

image.png

Now, delete the HelloWorld file:

rm src/components/HelloWorld.vue

TodoNew.vue

Now, add a new component TodoNew , which is responsible for creating new to-do items.

touch src/components/TodoNew.vue

Open TodoNew.vue and enter the following:

// src/components/TodoNew.vue

<template>
  <form @submit.prevent="addTodo">
    <input
      type="text"
      placeholder="Enter a new task"
      v-model="task"
    />
  </form>
</template>

Turning now to the component definition, there are two local state property - task and a new to-do provides a unique identifier of id .

// src/components/TodoNew.vue

<template>...</template>
<script>
export default {
  data() {
    return {
      task: "",
      id: 0
    };
  },
  methods: {
    addTodo: function() {
      //
    }
  }
};
</script>

Define store state

After a meeting, we will create a component that displays to-do items. Since it and the TodoNew component both need to access the same data, this is the ideal choice state

Now, go back to state and define the attribute state. Here we use the createStore function provided by Vux4, which returns an object. The object has a property todos , which is an empty array.

// src/store/index.js
import { createStore } from "vuex";

export default createStore({
  state () {
    return {
      todos: []
    }
  }
});

Define mutation

It can be known from Principle 2 that the Vuex state cannot be changed directly, and the function mutator

Now, we add a mutation store , and add a function attribute addTodo . The first parameter of mutator The second optional parameter is store, and the second is the data to be passed.

// src/store/index.js

import { createStore } from "vuex";

export default createStore({
  state () {
    return {
      todos: []
    }
  },
  mutations: {
    addTodo (state, item) {
      state.todos.unshift(item);
    }
  }
});

Use commit to call mutation

Now, you can TodoNew use its components, in TodoNew define a component addTodo method.

To access store , we can use the global attribute this.$store . Use the commit method to create a new mutation . Two parameters need to be passed-the first is mutation , and the second is the object we want to pass, which is a new to-do item (composed of id and task values).

// src/components/TodoNew.vue
methods: {
  addTodo: function() {
    const { id, task } = this;
    this.$store.commit("addTodo", { id, task });
    this.id++;
    this.task = "";
  }
}

review

so far:

  1. The user enters the to-do item through the input box and binds it to the variable task
  2. After submitting the form, the addTodo method will be called
  3. Create a to-do object and "submit" it to store .
// src/components/TodoNew.vue
<template>
  <form @submit.prevent="addTodo">
    <input
      type="text"
      placeholder="Enter a new task"
      v-model="task"
    />
  </form>
</template>
<script>
export default {
  data() {
    return {
      task: "",
      id: 0
    };
  },
  methods: {
    addTodo: function() {
      const { id, task } = this;
      this.$store.commit("addTodo", { id, task });
      this.id++;
      this.task = "";
    }
  }
};
</script>

Read store data

Now, we have created the function for adding to-do items. The next step is to display them.

Create a new component TodoList.vue file.

touch src/components/TodoList.vue

The content is as follows:

// src/components/TodoList.vue
<template>
<ul>
  <li
    v-for="todo in todos"
    :key="todo.id"
  >
    {{ todo.description }}
  </li>
</ul>
</template>

todos is a calculated attribute in which we return the contents of the Vuex store.

// src/components/TodoList.vue

<script>
export default {
  computed: {
    todos() {
      // 
    }
  }
};
</script>

Define getters

And direct access store different content, getter is similar to the function of calculating an attribute store. These tools are great for filtering or transforming data before returning it to the application.

For example, there is getTodos below, which returns an unfiltered state. In many cases, you can use filter or map to convert this content.

todoCount returns the length of the todo

By ensuring that the component is willing to keep a local copy of the data, getter helps achieve principle 1 , which is a single source of data.

// src/store/index.js

export default createStore({
  ...
  getters: {
    getTodos (state) {
      return state.todos;
    },
    todoCount (state) {
      return state.todos.length;
    }
  }
})

Returning to the TodoList component, we complete the function this.$store.getters.getTodos

// src/components/TodoList.vue

<script>
export default {
  computed: {
    todos() {
      return this.$store.getters.getTodos;
    }
  }
};
</script>

App.vue

To complete this application, all we have to do now is to import and declare our component App.vue

// src/App.vue

<template>
  <div>
    <h1>To-Do List</h1>
    <div>
      <TodoNew />
      <TodoList />
    </div>
  </div>
</template>
<script>
import TodoNew from "@/components/TodoNew.vue";
import TodoList from "@/components/TodoList.vue";

export default {
  components: {
    TodoNew,
    TodoList
  }
};
</script>

Do you really need Vuex?

Obviously, in large applications, having a global state management solution will help make our applications predictable and maintainable.

But for relatively small projects, sometimes I feel that using Vuex is too much to use, and it is more reasonable for everyone to follow the actual needs.

Advantages of

  • Easy to manage global status
  • Powerful debugging global status

Vuex disadvantages:

  • Additional project dependencies
  • Cumbersome template

~ End, I’m Shuawanzhi, I’ll do it, see you next time!


Original: https://vuejsdevelopers.com/2017/05/15/vue-js-what-is-vuex/

code is deployed, the possible bugs cannot be known in real time. In order to solve these bugs afterwards, a lot of time was spent on log debugging. By the way, I would like to recommend a useful BUG monitoring tool Fundebug .

communicate with

There are dreams and dry goods. search 160aee812f4229 [Great Move to the World] Follow this brushing wisdom who is still doing dishes in the early morning.

This article GitHub https://github.com/qq449245884/xiaozhi has been included, the first-line interview complete test site, information and my series of articles.


王大冶
68.1k 声望105k 粉丝