Review the Vuex
Vue-cli tool to create a project directly, check Vuex, other optional:
After creating the automatic installation dependency, start the project, write a simple demo to run the familiar helloWorld ~, then gradually implement a myVuex, to achieve the same desired result:
SRC/store/index. Js:
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
age: 7
},
getters: { // Say no more
getAge(state) { return state.age }
},
mutations: { Vuex specifies that all operations on state should be placed here and triggered by the commit method
changeAge(state, data) {
state.age = data ? data : ++state.age
}
},
actions: { Vuex specifies that asynchronous class functions are placed here, and the dispatch method is triggered
syncChangeAge({ state, commit }, data) {
state.age = 0
setTimeout(() = > {
this.commit('changeAge', data) / / I haven't find out what would stay here {commit} read, in the real Vuex without this also can run here
}, 1000); }},modules: { /** Vuex modules */}});Copy the code
SRC/App. Vue:
<template> <div id="app"> {{ showMe }} <button @click="$store.commit("changeAge")">increase</button> <button @click="$store.dispatch("syncChangeAge", 7)">reset</button> </div> </template> <script lang="js"> import Vue from "vue"; Export default Vue. The extend ({name: "App", computed: {showMe () {return ` I'm ${this. $store. Getters. GetAge | | "..." At the age of} `; }}}); </script>Copy the code
The running effect is as follows:
Note: Click the “add” button to add a year old, click the “reset” button to enter loading state for 1 second, and then set it to 7 years old. Now, import Vuex from “Vuex” introduced in stroe. Change to their own manual implementation, to achieve the same performance as this demo.
Ready Perfect
To start, write the code structure, create a Vuex folder, and write the first index file.
SRC/Vuex/index. Js:
class Store {
constructor(parameters) { // Vuex's core four pieces
this.state = {}
this.getters = {}
this.mutations = {}
this.actions = {}
}
get state() {
return this.state
}
commit(fName, data) {
this.mutations[fName].forEach(mutation= > mutation(data));
}
dispatch(fName, data) {
this.actions[fName].forEach(action= >action(data)); }}export default { Store }
Copy the code
Now that the simple structure of vuEX is complete, the collection of mutation and actions passed into the instance is handled, and the commit and Dispatch functions are provided to execute them.
Create the install
Vue. Use (Vuex) is called in store to inject the state manager into Vue.
Mixin Reference: VUE global mixin
According to the vue documentation, you must provide an install function to use use, and vue is passed in as an argument, see: vueUse
SRC/Vuex/index. Js:
class Store {... }const install = (Vue) = > {
Vue.mixin({
beforeCreate() {
const { store = null } = this.$options
if (store) {
this.$store = store
} else {
this.$store = this.$parent && this.$parent.$store
}
}
})
}
export default { Store, install }
Copy the code
Binding state
When you created Install in the previous step, you introduced Vue, mounted it globally to create an instance object, and used bidirectional data binding in Vue to implement state:
SRC/Vuex/index. Js:
let _Vue
class Store {
constructor(parameters) {
const { state = { } } = parameters
this.$vue = new _Vue({ // new A Vue instance receives the state passed in by the user
data: { state }
})
......
}
get state() { // Throws the state mounted on the Vue instance
return this.$vue.state
}
......
}
const install = (Vue) = >{ _Vue = Vue ...... }...Copy the code
Handling getter
Continue with the code above
.class Store {
constructor(parameters){... bindInstall(this, parameters)
}
.....
}
const install = (Vue) = >{... }const bindInstall = (store, options) = > {
/ / processing getters
const { getters } = options
if (getters) {
Object.keys(getters).forEach(key= > {
Object.defineProperty(store.getters, key, {
get() {
return getters[key](options.state)
}
})
})
}
}
export default { Store, install }
Copy the code
At this point, we can change the SRC /store/index import to our own:
// import Vuex from "vuex";
import Vuex from ".. /Vuex"; .Copy the code
Run the example and see that you have successfully gotten the getter in the store
Deal with mutations and actions
Continue with the bindInstall code:
.class Store {... }const install = (Vue) = >{... }const bindInstall = (store, options) = > { // Both collections are similar
const { getters, mutations, actions } = options
if (getters) { ... }
if (mutations) {
Object.keys(mutations).forEach(mutationName= > {
let storeMutations = store.mutations[mutationName] || []
storeMutations.push(data= > {
mutations[mutationName].call(store, store.state, data) // mutations the first argument of the function is state, and the second is the value
})
store.mutations[mutationName] = storeMutations
})
}
if (actions) {
Object.keys(actions).forEach(actionName= > {
let storeActions = store.actions[actionName] || []
storeActions.push(data= > {
actions[actionName].call(store, store, data) Vuex: vuex: vuex: vuex: vuex: vuex: vuex
})
store.actions[actionName] = storeActions
})
}
}
export default { Store, install }
Copy the code
Save, run the test – consistent with the initial demo results, and now implements the core VUex state manager
Here is the full Vuex/index.js code
let _Vue
class Store {
constructor(parameters) {
const { state = {} } = parameters
this.$vue = new _Vue({ data: { state } })
this.getters = {}
this.mutations = {}
this.actions = {}
bindInstall(this, parameters)
}
get state() { return this.$vue.state }
commit(fName, data) { this.mutations[fName].forEach(mutation= > mutation(data)) }
dispatch(fName, data) { this.actions[fName].forEach(action= > action(data)) }
}
const install = (Vue) = > {
_Vue = Vue
Vue.mixin({
beforeCreate() {
const { store = null } = this.$options
this.$store = store ? store : this.$parent ? this.$parent.$store : null}})}const bindInstall = (store, options) = > {
const { getters, mutations, actions } = options
if (getters) {
Object.keys(getters).forEach(key= > {
Object.defineProperty(store.getters, key, {
get() { return getters[key](options.state) }
})
})
}
if (mutations) {
Object.keys(mutations).forEach(mutationName= > {
let storeMutations = store.mutations[mutationName] || []
storeMutations.push(data= > { mutations[mutationName].call(store, store.state, data) })
store.mutations[mutationName] = storeMutations
})
}
if (actions) {
Object.keys(actions).forEach(actionName= > {
let storeActions = store.actions[actionName] || []
storeActions.push(data= > { actions[actionName].call(store, store, data) })
store.actions[actionName] = storeActions
})
}
}
export default { Store, install }
Copy the code