What is a VueX
Vuex is a state management mode developed specifically for vue.js applications. It uses centralized storage to manage the state of all components of an application and rules to ensure that the state changes in a predictable way.
Why VueX
The simplicity of one-way data flow can easily be broken when our application encounters state shared by multiple components:
- Multiple views depend on the same state.
- Actions from different views need to change the same state.
The shared state of components can therefore be extracted and managed in a global singleton:
- In this mode, our tree of components forms a giant “view” where any component can get state or trigger behavior no matter where it is in the tree!
- By defining and isolating concepts in state management and by enforcing rules to maintain independence between views and states, our code becomes more structured and maintainable.
The core concepts of VueX:
The difference between Vuex and pure global objects
At the heart of every Vuex application is the Store. A “store” is basically a container that contains most of the states in your app. Vuex differs from a purely global object in two ways:
- Vuex’s state storage is reactive. When the Vue component reads the state from the Store, if the state in the store changes, the corresponding component is updated efficiently accordingly.
- You can’t just change the state in the store. The only way to change the state in a store is to commit mutation explicitly. This allows us to easily track each state change, which allows us to implement tools that help us better understand our application.
Second, the core concept of VueX
1. state(Storage state)
State: page state management container object. Centralized storage of scattered data objects in Vue Components for unified state management. The page displays the required data to be read from this object.
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment (state) {
state.count++
}
}
})
Copy the code
State objects can now be obtained through store.state and state changes can now be triggered through the store.mit method
store.commit('increment')
console.log(store.state.count) // -> 1
Copy the code
2. getters(Processing state members to the outside world)
Sometimes we need to derive some state from the state in store. Vuex allows us to define “getters” (you can think of them as computed properties of the store) in the store. Just like evaluating properties, the return value of a getter is cached based on its dependency and is recalculated only if its dependency value changes
(1) The Getter accepts state as its first argument
const store = new Vuex.Store({
state: {
todos: [
{ id: 1, text: '...', done: true },
{ id: 2, text: '...', done: false }
]
},
getters: {
doneTodos: state => {
return state.todos.filter(todo => todo.done)
}
}
})
Copy the code
(2) Access through attributes
Getters are exposed as store.getters objects, and you can access these values as properties
store.getters.doneTodos // -> [{ id: 1, text: '...', done: true }]
Copy the code
Getters can also accept other getters as second arguments:
getters: {
// ...
doneTodosCount: (state, getters) => {
return getters.doneTodos.length
}
}
store.getters.doneTodosCount // -> 1
Copy the code
(3) Access through methods
You can also pass parameters to a getter by asking the getter to return a function. It’s useful when you’re querying an array in a store.
getters: { // ... getTodoById: (state) => (id) => { return state.todos.find(todo => todo.id === id) } } store.getters.getTodoById(2) // -> { id: 2, text: '... ', done: false }Copy the code
3. mutations(State member operation)
The only way to change the state in Vuex’s store is to commit mutation. Mutations in Vuex are very similar to events: each mutation has a string event type (type) and a callback function (handler). This callback is where we actually make the state change, and it takes state as the first argument:
Const store = new Vuex. Store ({state: {count: 1}, mutations: {increment (state) {/ / the status state. Count++}}})Copy the code
“This function is called when a mutation of type INCREMENT is triggered.” To wake up a mutation handler, you need to call the store.mit method with the corresponding type:
store.commit('increment')
Copy the code
You can pass in an additional parameter, payload, to store.mit.
mutations: {
increment (state, n) {
state.count += n
}
}
store.commit('increment', 10)
Copy the code
In most cases, the payload should be an object, which can contain multiple fields and the mutation recorded will be more readable
mutations: {
increment (state, payload) {
state.count += payload.amount
}
}
store.commit('increment', {
amount: 10
})
Copy the code
Note: Mutation must be a synchronization function in Vuex, and Mutation is a synchronous transaction
4. actions(Asynchronous operation)
Action is similar to mutation, except that:
- The Action commits mutation rather than a direct state change.
- Actions can contain any asynchronous operation.
The Action function accepts a context object with the same methods and properties as the store instance, so you can submit a mutation by calling context.mit. Or get state and getters via context.state and context.getters. Action is triggered by the store.dispatch method:
store.dispatch('increment')
Copy the code
Mutation must be executed synchronously, so the Action is not bound! We can perform asynchronous operations within the Action
actions: {
incrementAsync ({ commit }) {
setTimeout(() => {
commit('increment')
}, 1000)
}
}
Copy the code
Actions support the same payloads and objects for distribution:
// Distribute store.dispatch('incrementAsync', {amount: 10}) // distribute store.dispatch({type: 'incrementAsync', amount: 10})Copy the code
Here’s a question: why isn’t the context object the Store instance itself?
5. modules(Modular state management)
Because of the use of a single state tree, all the states of an application are grouped into one large object. When the application becomes very complex, the Store object can become quite bloated.
To solve these problems, Vuex allows us to split the Store into modules. Each module has its own state, mutation, action, getter, and even nested submodules — split the same way from top to bottom:
const moduleA = { state: () => ({ ... }), mutations: { ... }, actions: { ... }, getters: { ... } } const moduleB = { state: () => ({ ... }), mutations: { ... }, actions: { ... } } const store = new Vuex.Store({ modules: { a: moduleA, b: ModuleB}}) Store.state. a // -> moduleA status Store.state. b // -> moduleB statusCopy the code
Local state of a module
For mutation and getters inside a module, the first argument received is the module’s local state object.
const moduleA = { state: () => ({ count: 0 }), mutations: {increment (state) {// where the 'state' object is the local state of the module state.count++}}, getters: { doubleCount (state) { return state.count * 2 } } }Copy the code
Similarly, for actions within the module, the local state is exposed through context.state and the rootState is context.rootstate
const moduleA = {
// ...
actions: {
incrementIfOddOnRootSum ({ state, commit, rootState }) {
if ((state.count + rootState.count) % 2 === 1) {
commit('increment')
}
}
}
}
Copy the code
For getters inside the module, the root node state is exposed as a third parameter:
const moduleA = {
// ...
getters: {
sumWithRootCount (state, getters, rootState) {
return state.count + rootState.count
}
}
}
Copy the code
Refer to the link
VueX website links: vuex.vuejs.org/zh/ Vue VueX of learning notes: segmentfault.com/a/119000001… Installation and usage of VueX: www.jianshu.com/p/ec1b53edc…
Writing level is limited, write more disorderly, if there is a mistake, please correct ~