vue from introduction to mastery [vuex] (VII)
Vuex is a large public warehouse. Vuex can help us manage shared state, with more concepts and frameworks.
Vuex implements a one-way data flow. It has a state to store data globally. When a component wants to change the data in the state, it must do so through changes. Changes also provides a subscriber mode for external plug-ins to call to obtain the update of state data. When all asynchronous operations (commonly used to call the back-end interface to obtain data asynchronously) or batch synchronous operations need to go through actions, but actions cannot directly modify the state, you still need to trigger the methods in changes and then modify the state data through changes. After the data is changed, it is pushed to the component, and the component is re rendered to the view.
Vuex is the state manager of vue, and the stored data is responsive. But it will not be saved. After refreshing, it will return to the initial state. The specific method is to copy and save a copy of the data in vuex to localStorage when the data changes. After refreshing, if there is saved data in localStorage, take it out and replace the state in the store.
Core: State, Getter, Mutation, Action, Module
- state: contains the states stored in the store.
- getter: similar to the calculation property in Vue, the return value is calculated according to other getters or state s.
- mutation: a group of methods, which are the executors of changing the state in the store. They can only be synchronous operations.
- action: a set of methods that can contain asynchronous operations.
- module: modular management
1, Installation
npm install vuex --save yarn add vuex
2, Create warehouse
Create a store folder under src and an index js
import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0, name:"zhangsan" }, getter: { doneTodos: (state, getters) => { return state.todos.filter(todo => todo.done) } }, mutations: { increment (state, payload) { state.count++ } }, actions: { addCount(context) { // Can include asynchronous operations // Context is a context object with the same methods and properties as the store instance } } }) export default store;
Modify main js:
import Vue from 'vue'; import App from './App'; import router from './router'; import store from './store'; // Introduce the store object we exported earlier Vue.config.productionTip = false; new Vue({ el: '#app', router, store, // Add the store object to the vue instance components: { App }, template: '<App/>' });
Finally, modify app vue:
<template> <div></div> </template> <script> export default { mounted() { // Use this$ store. state. XXX has direct access to the status in the warehouse console.log(this.$store.state.name); } } </script>
At this point, start the project npm run dev to output the value of name we just defined in the store on the console.
3, Use
State is similar to data in vue
Vuex uses state to store the state that needs to be shared in the application. In order to make Vue components change after the state is changed, you need to create calculated properties based on the state.
const state = { count:"", storeId:"", storeName:'' }
1. Use
{{this.$store.state.count}} (no cache, do not use)
2.computed (with cache)
If the data is not updated, go to the cache to get the latest data
computed: { //It has the function of data cache count() { return this.$store.state.count; }}
3.mapState auxiliary function
//Import import { mapState } from 'vuex' computed:mapState(["count","num","apple"]) computed:mapState({ c:state => state.count, n:"num", result(state){ return state.count + state.num } }) computed:{ ...mapState(["count","num","apple"]), hw(){ return "hello world!" } }
Note: / / it cannot be modified directly (the page value can change, but the warehouse value remains unchanged). The modification is handled by the warehouse administrator
this.$store.state.count++;
//Handle ---- "changes" through the warehouse administrator
const store = new Vuex.Store({ state: { count: 1 }, mutations: { increment (state) { // Change status state.count++ } } })
Store. Needs to be called with the corresponding type Commit method:
store.commit('increment')
Getter is similar to calculating properties in Vue
Similar to the calculation attribute in Vue (it can be considered as the calculation attribute of Store, which processes the data in the Store to form new data), the return value of getter will be cached according to its dependency, and will be recalculated only when its dependency value changes.
The Getter method accepts state as its first parameter:
1. Use
{{this.$store.getters.donearr}} don't use it without cache
2.computed
computed:{//Role of cache donearr(){ return this.$store.getters.donearr } }
3.mapGetters auxiliary function
import { mapGetters } from 'vuex' computed: { ...mapGetters(['donearr']) }
Mutations is similar to methods synchronization in vue
Why can't you use direct asynchrony in Mutation
Mutation is used to change the data in the Store.
The data in the Store can only be changed through a mutation. You can't directly operate the data in the Store. You can modify it by commit ting a mutation. Its essence is actually a function
In this way, although the operation is a little cumbersome, it can centrally monitor the changes of all data
The mutation operation must be synchronized
Every time we submit a mutation, we will have a record. Vuex does this to make it easier to record the history and track of each data change, and to facilitate operations such as listening and rollback
1. Use the mutation defined in js to call through commit
mutations:{ addcount(state,payload){ state.count+=payload;//Change status } },
// Trigger mutation in component changecount(){ //It is handled by the warehouse administrator // The first way to trigger changes this.$store.commit("addcount",{n:100,m:1000});}
2. Pass parameters when triggering changes:
// store.js mutations: { addN(state, step) { //The first parameter is state, and the following parameter is store The additional parameter passed in by commit, that is, the payload of mutation state.count += step } } // In component this.$store.commit('addN', 3) // When the commit function is called, the commit parameter is carried
3.mapMutations auxiliary function
// 1. Import mapMutations function from vuex as needed import { mapMutations } from 'vuex' // 2. Map the specified changes function to the methods function of the current component through the mapchanges function just imported methods: { ...mapMutations(['add', 'addN']) }
Actions is similar to methods asynchronous in vue
● the Action submits the Mutation instead of directly changing the status. (through Mutation)
● Action can contain any asynchronous operation.
vueX: Note: context --- {commit dispatch, state...}
Note: do not perform asynchronous operations in the mutations function, such as adding a delayer
Only the functions defined in changes have the right to modify the data in state; In actions, you cannot directly modify the data in state. You must use context Commit triggers a mutation.
Context: context object, which is equivalent to this in the arrow function. It has the same properties and methods as the store instance
payload: mounted parameter
actions:{ addcountA(context,n){ console.log(context,n); setTimeout(function(){ context.commit("addcount",n); },1000) } }
1. Use dispatch
// store.js const store = new Vuex.store({ //... Omit other codes actions: { addAsync(context, payload) { setTimeout(() => { context.commit('add') }, 1000) } } }) // Trigger Action in component methods: { handle() { this.$store.dispatch('addAsync', 3) } }
2. mapActions auxiliary function
<button @click="changecountA(5000)">modify countA</button> import { mapState,mapActions} from 'vuex' ...mapActions({ changecountA: 'addcountA' // Add ` this Changecounta() ` mapped to ` this$ store. dispatch('addcountA')` })
Modules module
The store can be divided into modules. Each module has its own state, mutation, action, getter, and even nested sub modules
The function of named true is to tell vuex that all things in the module's state, getters, variations and actions need to be added with a namespace when calling. This namespace is the name of the module when it is improved.
//ModuleA.js const moduleA = { namespaced: "true", state: { msg: "moduleA...", name: "lili", age: 28 } } export default moduleA;
1. Use
this.$store.state.a.msg;
2.computed
msg() { return this.$store.state.a.msg; }
3. Usage of auxiliary functions: 3
- 3.1 arrow function
import { mapState } from "vuex"; ...mapState({ msg: (state) => state.a.msg, name: (state) => state.a.name, age: (state) => state.a.age, })
- 3.2 array form
import { mapState } from "vuex"; ...mapState("a",["msg","name","age"])
- 3.3 through auxiliary functions
You can create helper functions based on a namespace by using createNamespacedHelpers. It returns an object with a new component binding auxiliary function bound to the given namespace value:
import { createNamespacedHelpers } from 'vuex' const { mapState } = createNamespacedHelpers('a') ...mapState(["msg","name","age"])
4, Function
It can easily realize the data sharing between components
Benefits of using Vuex to uniformly manage state:
● it can centrally manage the shared data in Vuex, which is easy to develop and maintain later
● it can efficiently realize data sharing between components and improve development efficiency
● the data stored in Vuex is responsive and can keep the data synchronized with the page in real time
What kind of data is suitable for storage in Vuex
Generally, only the data shared between components is necessary to be stored in Vuex; The private data of the component can still be stored in the data of the component itself.
-
Multiple views depend on the same state: for example, data sharing among multiple components can get user information on different pages
-
Behaviors from different views need to change the same state: for example, user member information can be changed on different pages