Reference Documents:
- Vex4. x Official document
What is Vuex
Vuex is a state management mode + library 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.
This state self-management application consists of the following parts:
- State, the data source that drives the application;
- Views, which declaratively map state to views;
- Action in response to changes in state caused by user input on the view.
How Vuex works is shown below:
Simple use of vex4.x
Create a Store instance
import { createApp } from 'vue'
import { createStore } from 'vuex'
// Create a new store instance
const store = createStore({
state () {
return {
count: 0}},getters: {
double(state){
return state.count * 2}},mutations: {
increment (state, payload) {
state.count++
}
},
actions: {
AsyncIncrement(state, payload){
return new Promise((resolve, reject) = > {
setTimeout(() = > {
commit('someMutation', payload)
resolve()
}, 1000)})}})const app = createApp({ /* Root component */ })
// Install the Store instance as a plug-in
app.use(store)
Copy the code
Use by means of a composite API
Access State and Getter
import { computed } from 'vue'
import { useStore } from 'vuex'
export default {
setup () {
const store = useStore()
return {
// Access state in a computed function
count: computed(() = > store.state.count),
// Access the getter in a computed function
double: computed(() = > store.getters.double)
}
}
}
Copy the code
Access Mutation and Action
import { useStore } from 'vuex'
export default {
setup () {
const store = useStore()
return {
/ / using mutation
increment: () = > store.commit('increment'),
/ / use the action
asyncIncrement: () = > store.dispatch('asyncIncrement')}}}Copy the code
Compare vex3. x in usage
- create
store
The method is different from that used to be throughnew Store()
To create astore
Instance. Now it’s throughcreateStore
Method to create. - Vex4.x is compatible with previous use methods. But in Vue3. X, if we want to use Vuex via a composite API approach, we need to use the
useStore
This function.
Implement a simple vex4.x;
To implement acreateStore
methods
Store is actually implemented as a Class, but instead of exposing the store Class directly, it is wrapped as a function that returns an instance directly.
import { reactive } from 'vue'
export function createStore(options){
return new Store(options)
}
class Store{
constructor(options){
const store = this;
// Use reactive to make state reactive
store._state = reactive({data: options.state})
}
get state() {return this._state.data
}
}
Copy the code
throughObject.defineProperty
To redefine getters
Define all getters passed in by the user to the Store instance’s getters property, which is called when the value is fetched
function forEachValue(obj, fn){
Object.keys(obj).forEach(key= > fn(obj[key], key))
}
class Store{
constructor(options){
const store = this;
// Use reactive to make state reactive
store._state = reactive({data: options.state})
/ / save getters
const _getters = options.getters;
store.getters = {};
forEachValue(_getters, function(fn, key){
Object.defineProperty(store.getters, key, {
get: () = > fn(store.state),
enumerable: true}}})})Copy the code
Implement based on publish and subscribe modelmutations
和 actions
class Store{
constructor(options){
// ...
const store = this;
store._mutations = Object.create(null)
const _mutations = options.mutations;
forEachValue(_mutations, (mutation, key) = >{
store._mutations[key] = (payload) = > {
mutation.call(store, store.state, payload)
}
})
}
commit = (type, payload) = > {
this._mutations[type](payload)
}
}
Copy the code
Action is similar to mutation, except that:
- The Action commits mutation rather than a direct state change.
- Actions can contain any asynchronous operation
Since an action can execute asynchronous functions, the action should return a Promise instance to verify the result of dispact execution. If it is not a Promise, make it a Promise.
class Store{
constructor(options){
// ...
const store = this;
store._actions = Object.create(null)
const _actions = options.actions;
forEachValue(_actions, (action, key) = >{
store._actions[key] = (payload) = > {
const res = action.call(store, store.state, payload)
if(! isPromise(res)){return Promise.resolve(res)
}
return res
}
})
}
dispatch = (type, payload) = > {
this._actions[type](payload)
}
}
Copy the code
useStore
Get the registered Store instance by inject
import {inject} from 'vue'
export function useStore(injectKey = null) {
return inject('store')}Copy the code
install
To use Vuex in a Vue project, we need to register the store with use()
const app = createApp({ /* Root component */ })
// Install the Store instance as a plug-in
app.use(store)
Copy the code
class Store{
install(app, injectKey){
// Vue3.x createApp().use(store)
// globally exposes a variable that exposes an instance of store
app.provide('store')
// Vue2.x Vue.prototype.$store = this
// Add the $store attribute so that you can use $store.state.count directly in the template
app.config.globalProperties.$store = this; }}Copy the code