Introduction, Installation and initialization
What is a vuex
VueX is a state management tool suitable for use in Vue project development. Vue provides a unified management tool — VueX — for these values that are frequently used by multiple components. In a Vue project with VueX, we just need to define these values in the VueX to be used in the components of the entire Vue project.
How do I install vuex
NPM install
npm i vuex -s
Copy the code
How to use Vuex
Create index.js in a new store folder under the root of your project
The project’s SRC folder looks like this
│ App. Vue │ main. Js │ ├ ─ assets │ logo. The PNG │ ├ ─ components │ HelloWorld. Vue │ ├ ─ the router │ index. The js │ └ ─ store index, jsCopy the code
In the store.js file, introduce vuex and use vuex, noting that the variable names are capitalized Vue and vuex
//store.js
import Vue from 'vue'
import Vuex from 'vuex'
/ / mount Vuex
Vue.use(Vuex)
// Create a VueX object
const store = new Vuex.Store({
state: {// The stored key-value pair is the state to be managed
name:'helloVueX'}})export default store
Copy the code
Mount store into the Vue instance of the current project
//main.js
import store from './store'
new Vue({
el: '#app',
router,
store, // Just like the router, mount the Vuex instance we created into the vue instance
render: h= > h(App)
})
Copy the code
Use Vuex in components
For example, in app.vue, we take the name defined in state and display it in the H1 tag
<template>
<div id='app'>
name:
<h1>{{ $store.state.name }}</h1>
</div>
</template>
Copy the code
Or use it in a component method
methods:{
add(){
console.log(this.$store.state.name)
}
},
Copy the code
Detailed usage methods will be described below
Note: the emergence of vuex is to solve the problem of communication between components, if an action or data does not involve public action, only a single component operations, do not store the status value or function to the vuex, because vuex would make their own mount on all components, whether or not the current component used the contents, so this fact Definitely adds to the performance loss.
The core of VueX
In VUex, there are five basic objects by default:
- State: Storage state (variable)
- getters: recompile the data before fetching it
state
Compute properties of. - 2. mutations: Changes the status, and it’s simultaneous. This is similar to custom events in our component.
- Actions: Asynchronous operations.
- modules:
store
A child of the module
Split into single files
If the project status and methods too much, the index. The js file will look very bloated and poor maintenance, this time we can state, getters, mutations, the actions into a single file, is helpful to manage
The directory structure looks like this
Store │ │ ├ ─ index. Js │ │ ├ ─ state. The js │ │ ├ ─ getters. Js │ │ ├ ─ mutations. Js │ │ └ ─ actions. JsCopy the code
index.js
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
actions,
getters,
});
Copy the code
Other files only need export and export
state.js
export default {
name:'hzw'
};
Copy the code
mutations.js
export default {
changeName(state, name){ state.name = name; }};Copy the code
getters.js
export default {
realName(state) {
return "Name:" + state.name
},
};
Copy the code
actions.js
export default {
changeName({ commit }, name) {
return commit('changeName', name)
}
};
Copy the code
This makes it look more structured and easier to maintain
The state and the mapState
What is the state
The state (vuex) material data (vue)
Vuex’s state has many similarities with VUE’s data in that it is used to store some data, or state values. These values will be mounted to the bi-directional binding event between the data and the DOM, which triggers dom updates when the value changes.
We declare a state count in state.js, with an initial value of 0, and then print it in the component
// state.js
export default {
count:'0'
};
Copy the code
/ / components
<template>
<div class="hello">
<h3>{{$store.state.count}}</h3>
</div>
</template>
Copy the code
The result is shown below
Note: Although state and data have a lot in common, state is generally mounted on computed properties of child components when used, which makes it easier to respond to child components when the value of state changes. If you use data to receive $store.state, you can also receive the value, but since this is a simple assignment, state changes cannot be heard by data in vue. Watch $Store can also solve this problem, but it is a bit troublesome.
So, it’s best to use computed to receive state, as follows, and I’ll show you how to modify state later.
//mutations.js
export default {
add(state, n = 0) {
return (state.count += n)
},
reduce(state, n = 0) {
return (state.count -= n)
}
}
Copy the code
/ / components
<template>
<div class="hello">
<h3>{{$store.state.count}}</h3>
<div>
<button @click="add(10)">increase</button>
<button @click="reduce(10)">To reduce</button>
<div>computed:{{dataCount}}</div>
<div>data: {{count}}</div>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
data () {
return {
dataCount: this.$store.state.count // Receive with data}},computed: {count(){
return this.$store.state.count // Use computed reception}},methods: {
add(n){
this.$store.commit('add',n);
},
reduce(n){
this.$store.commit('reduce',n); }}}</script>
Copy the code
Then we click on the add button and see what happens. What happens
As you can see, values received with data do not respond to updates in a timely manner, as can be done with computed.
Initialization of Props, Methods,data, and computed is done between beforeCreated and created.
What is the mapState
MapState is an auxiliary function of state
What it actually does: When a component needs to fetch multiple states, it can be repetitive and redundant to declare all those states as computed properties. To solve this problem, you can use the mapState helper function to help generate computed properties
How to use it: Import this helper function first.
import { mapState } from 'vuex'
Copy the code
Then you can use mapState in computed
When using auxiliary functions such as mapState, if the names inside the component are the same as those in VUEX, you can abbreviate them to arrays.
//state.js
export default {
nickname:'Simba'.age:20.gender:'male'
};
Copy the code
//computed
computed: mapState(['nickname'.'age'.'gender'])
// The following code is much more concise
computed: {nickname(){return this.$store.state.nickname}
age(){return this.$store.state.age}
gender(){return this.$store.state.gender}
}
Copy the code
If you need to customize a calculated property, you need the expansion operator in ES6:…
data(){
return{
count:14}}computed: {
value(){
return "Name:" + this.coount/7
},
...mapState(['nickname'.'age'.'gender'])}Copy the code
Getters and mapGetters
What is the getters
Getters: The return value of getters is cached according to its dependencies, and is recalculated only if its dependencies change. This is roughly equal to computed in Vue. You can use getters just as you use computed, but there are differences.
How do I use Getters
Methods in getters take two default arguments
- stateThe current
VueX
The state object in the object - gettersThe current
getters
Object that will be used togetters
The othergetter
Use them
//state.js
export default {
name:'simba'.age:'20'
};
//getters.js
export default {
// The first argument is state
realName(state) {
return "Name:" + state.name
},
// The second argument accesses getters
nameAndAge(state, getters) {
return "Age." + state.age +";"+ getters.realName
}
};
Copy the code
How do I access Getters
Access by property
Getters are exposed as store.getters objects, and we can access these values as properties:
store.getters.realNameName :simba
Copy the code
Note that getters are cached as part of Vue’s responsive system when accessed through properties.
Access by method
We can do this by asking getters to return a function. This is useful when querying an array in a store.
state:{
todos:[
{
id:2.text:'... '.done: false}},getters: {
getTodoById: (state) = > (id) = > {
return state.todos.find(todo= > todo.id === id)
}
}
store.getters.getTodoById(2) // -> {id: 2, text: '... ', done: false}
Copy the code
Note that the getter is called every time it is accessed through a method and does not cache the result.
Used in components
In computed, we bind a computed property with this.$store.getters. XXX
/ / components
<template>
<div class="hello">
<div>
<div>{{message}}</div>
<div>{{message2}}</div>
</div>
</div>
</template>
computed:{
message(){
return this.$store.getters.realName
},
message2(){
return this.$store.getters.nameAndAge; }},Copy the code
The results are as follows:
What is a mapGetters
The mapGetters helper function simply maps the getters in the store to local computed properties:
How to use it: Import this helper function first.
import { mapGetters } from 'vuex'
Copy the code
Then you can use mapGetters in computed
computed: { ... mapGetters({message: "realName".message2: "nameAndAge"})},Copy the code
If the name of the evaluated property is the same as the name of getters, you can also use the array abbreviation
computed: { ... mapGetters(["realName"."nameAndAge"])},Copy the code
Mutation and mapMutation
What is a mutation
Mutation is a collection of methods that operate on state data, such as modifying, adding, deleting, and so on. Mutation usually stores some methods to synchronize the modified state.
Note: The only way to change the state in Vuex’s store is to commit mutation.
How to use mutation
Mutations methods all have a default parameter: mutation([state] [,payload])
- stateThe current
VueX
The object of thestate
- Payload (parameter that the method passes when it is called)
//state.js
export default {
name:'Han Zhiwei'
};
//mutations.js
export default {
changeName(state, name){ state.name = name; }};Copy the code
We need to call mutation like this
this.$store.commit('changeName'.Daniel Wu)
Copy the code
For example, let’s modify the name attribute in the component’s Methods
methods: {
changeName(name){
this.$store.commit('changeName',name); }},// Call changeName
mounted(){
this.changeName(Daniel Wu)}Copy the code
When you need multiple parameter submissions, you can put them in one object
this.$store.commit('changeName', {firstName:'han'.lastName:'zhiwei'})
Copy the code
You can also pass the parameter in another way
this.$store.commit({
type:'changeName'.payload: {firstName:'han'.lastName:'zhiwei'}})Copy the code
What is a mapMutation
The mapMutation helper function simply maps mutation in store to component methods
How to use it: Import this helper function first.
import { mapMutation} from 'vuex'
Copy the code
You can then use mapMutation in methods
methods: {... mapMutations({changeName:'changeName'})},Copy the code
This code is equivalent to the following
changeName(payLoad){
this.$store.commit('changeName',payLoad)
}
Copy the code
If the method name is the same as the mutation name, it can be shortened as follows
methods:{ ... mapMutations(['changeName'])}Copy the code
You can also use constants instead of the Mutations event type
Create a new mutation-types. Js file under the Store folder
//mutation-types.js
export const ADD_AGE = 'ADD_AGE'
//mutations.js
import * as types from './mutation-types';
export default {
[types.ADD_AGE](state, payLoad) {
state.age += payLoad.number
}
}
// The js part of the component. mapMutations([types.ADD_AGE]),Copy the code
But this is not very commonly used, it is ok to know this knowledge point
Add or delete members in state
Now that we’ve talked about how to change the value of state, by the way, how to add or remove members of state
Vue. Set Sets the value of a member for an object, or adds it if it does not exist
Vue.set(state,"age".22)
Copy the code
Vue.delete Deletes a member
Vue.delete(state,'age')
Copy the code
The actions and mapActions
What are the actions
Because asynchronous operations are performed directly in the mutation method, data failure may occur. So Actions are provided specifically for asynchronous operations, similar to AXIOS requests, and ultimately to modify the values in state by submitting the mutation method.
How to use Actions
Methods in Actions have two default parameters: Action([context] [,payload])
- contextContext objects contain
dispatch
commit
state
getters
rootState
You can usees6
The deconstruction assignment of the{ commit }
- Payload (parameter that the method passes when it is called)
Look at an example of a mutation that modifies the name attribute in state after a second
//state.js
export default {
name:'Han Zhiwei'
};
//mutations.js
export default {
changeName(state, name){ state.name = name; }};//actions.js
export default {
asyncChangeName({ commit } ,name) {
setTimeout(() = > {
commit('changeName',name);
}, 1000); }};Copy the code
We need to call the action this way
this.$store.dispatch('asyncChangeName'.Daniel Wu)
Copy the code
For example, let’s modify the name attribute in the component’s Methods
methods: {
changeName(name){
this.$store.dispatch('asyncChangeName',name); }},// Call changeName
mounted(){
this.changeName(Daniel Wu)}Copy the code
You can also call another action from an action
//actions.js
export default {
asyncChangeName({ dispatch }) {
setTimeout(() = > {
dispatch('anotherAction');
}, 1000);
},
anotherAction(){
console.log('Another action has been called')}};Copy the code
Action can also pass in state, and rootState
//actions.js
export default {
action({ state }) {
setTimeout(() = > {
console.log(state.name)
}, 1000);
},
anotherAction({ rootState }){
setTimeout(() = > {
console.log(rootState.name);
}, 1000); }};Copy the code
For actions, the mutation is the same
this.$store.dispatch('changeName', {firstName:'han'.lastName:'zhiwei'})
Copy the code
What is a mapActions
The mapActions helper function simply maps the Actions in the store to the component methods
How to use it: Import this helper function first.
import { mapActions} from 'vuex'
Copy the code
Then you can use mapActions in methods
methods:{ ... mapActions({changeName:'changeName'})},Copy the code
This code is equivalent to the following
changeName(payLoad){
this.$store.dispatch('changeName',payLoad)
}
Copy the code
If the method name is the same as the actions name you can abbreviate it like this
methods:{ ... mapActions(['changeName'])}Copy the code
Modules modular
What are the modules
When a project is large and has many states, modular management can be adopted. Vuex allows us to split the Store into modules. Each module has its own state, mutation, action, and getter.
Initialize the modules
We learned how to split vuex’s index.js file into a single file for management, so we will still split all modules into a single file for management
Store │ ├ ─ index. Js │ ├ ─ state. The js │ ├ ─ getters. Js │ ├ ─ mutations. Js │ ├ ─ actions. Js │ └ ─ modules │ ├ ─ moduleA// moduleA has the same structure as moduleB│ ├─ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.js │ ├─ ├.jsCopy the code
1. The first root index. In addition to the introduction of its own state in js, getters, mutations, actions, and to introduce two modules of the index, js and export modules in the export
import Vue from 'vue';
import Vuex from 'vuex';
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
import moduleA from './modules/moduleA/index';
import moduleB from './modules/moduleB/index';
Vue.use(Vuex);
export default new Vuex.Store({
state,
mutations,
actions,
getters,
modules: {
moduleA,
moduleB,
},
});
Copy the code
2. In moduleA index. Js import moduleA state, getters, mutations, actions. ModuleB similarly
Getters, mutations, and actions are all registered in the global namespace by default, so we can use them in the same way as the root state by default, which makes modularity meaningless, so we need to add namespaced to the module’s index.js: True makes it a module with namespaces. When a module is registered, all its getters, actions, and mutations are automatically named according to the path the module was registered with.
import state from './state';
import getters from './getters';
import mutations from './mutations';
import actions from './actions';
const moduleA = {
namespaced: true.state: state,
getters: getters,
mutations: mutations,
actions: actions,
};
export default moduleA ;
Copy the code
3. The state under the moduleA, getters, mutations, actions like before learning the export
//state.js
export default {
name:'hzw'
};
//mutations.js
export default {
changeName(state, name){ state.name = name; }};// And so on
Copy the code
How is this defined in modularity
state
Write them in their own state.js
getter
In the getter, it takes three parameters, the first is the module state, the second is the module getters, and the third is the root node state rootState
//getters.js
export default {
nameAndAge(state, getters, rootState) {
return "Age." + state.age +";"+ getters.realName + "" + rootState.name
}
};
Copy the code
mutation
The first parameter passed in for mutation is also a state in the module, just as the root state was defined for mutation
export default {
// State is the local state of the module
changeName(state, name){ state.name = name; }};Copy the code
actions
For action, it will pass in only the context object, where the state property refers to the state in the module and the rootState refers to the rootState, as follows
export default {
changeName({ state,rootState }) {
console.log(state.name)
console.log(rootState .name)
}
};
Copy the code
How do you develop in modularity
1. The state
This requires a module name in front of the original state name to fetch objects in the module.
this.$store.state.moduleA.name;
Copy the code
The same is true for auxiliary functions, where name is preceded by the module name
. mapState({name: state= > state.moduleA.name,
})
/ / short. mapState('moduleA'['name']),
Copy the code
Get the state of the root node as before, without adding the module name or root
. mapState(['name']),
Copy the code
2. The getters
This also requires a module name in front of the original state name to fetch objects in the module.
Getters in the root state do not require a module name
store.getters.moduleA.realName
// The first parameter of the map function also needs the module name
computed: {
// Get getters under moduleA. mapGetters("moduleA"["realName"."nameAndAge"])
// Get the root getters. mapGetters(["realName"])},Copy the code
Call mutation and action
Based on the calculation of state and getters, mutation and action calls in the module must also add the module name
No module name is required when calling mutation and action in the root state
methods:{
// Call the action under module A. mapActions('moduleA'['changeName'])
// call mutation under module A. mapMutation('moduleB'['changeName'])
// Call the root action. mapActions(['changeName'])
// invoke mutation in root state. mapMutation(['changeName'])}Copy the code
4. It is important to note that {root:true} is passed in as a third argument to action and mutation in the root state of the action and mutation in the module
/ / moduleA actions. Js
export default {
AsyncChangeName({ commit } ,name) {
setTimeout(() = > {
// mutation is called in the root state
commit('changeName',name,{ root: true });
// Call the root action
dispatch('changeName',name,{ root: true });
}, 1000); }};Copy the code
5. Register the actions in the module as global
When declaring an action, add root:true and place the action definition in the hanler function as follows:
//actions.js
export default {
globalAction: {root:true.handler({ commit } ,name) {
setTimeout(() = > {
commit('changeName',name);
}, 1000); }}};Copy the code
Now you’re ready to use Vuex for development tasks!
Make an advertisement
This is my open source favorites url project
Project address 👉👉 Click to enter, you can directly set as the browser home page or desktop shortcut for use, I am using, long-term maintenance.
Completely open source, you can research, secondary development. Of course, you are still welcome to click Star⭐⭐⭐ 👉 ⭐ source link (gitee) Source link (github) source link (Github)
Links to integrate
🔊 Project preview address (GitHub Pages):👉👉alanhzw.github. IO
🔊 Project preview alternate address (own server):👉👉warbler.duwanyu.com
🔊 source code address (gitee):👉👉gitee.com/hzw_0174/wa…
🔊 source address (github):👉👉github.com/alanhzw/War…
🔊 My blog :👉👉www.duwanyu.com