Vuex
Project creation
In the previous article, we wrote a simple vuE-Router by hand. This time, we will challenge vuex to implement basic functions. As always, let’s create a project and use Vuex
Related components and VUEX configuration
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h= > h(App)
}).$mount('#app')
Copy the code
App.vue
<template>
<div id="app">
<div class="hello">
<p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
<p @click="$store.dispatch('add')">async: {{$store.state.counter}}</p>
</div>
</div>
</template>
<script>
export default {
name: 'HelloWorld',}</script>
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
Copy the code
Then the vuex configuration store/index.js
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
counter: 0
},
mutations: {
add(state) {
state.counter++
}
},
actions: {
add({commit}) {
setTimeout(() = > {
commit('add')},1000); }}})Copy the code
Project start
This successfully implements the use of VUex in components
Now our goal is to code our own VUEX
Handwritten Vuex
Documents to prepare
Create myStore file
main.js
import Vue from 'vue'
import App from './App.vue'
// import store from './store'
import store from './mystore' //store points to change
Vue.config.productionTip = false
new Vue({
store,
render: h= > h(App)
}).$mount('#app')
Copy the code
mystore/index.js
import Vue from "vue";
import Vuex from "./myvuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
counter: 0,},mutations: {
add(state){ state.counter++; }},actions: {
add({ commit }) {
setTimeout(() = > {
commit("add");
}, 1000); }}});Copy the code
Demand analysis
As with vuE-Router, the following requirements need to be implemented in order to implement Vuex:
- To use vuex as a plug-in, you need to implement the Store class and install method
- Implementation of the Sotre class:
- You need responsive data state
- The Store instance needs to be mounted to the Vue instance
- Commit and Dispatch methods implemented
Vuex basic structure
Recall the steps you took when using vuex
- First introduced
import Vuex from 'vuex'
- To install
Vue.use(Vuex);
- Final instantiation
new Vuex.Store({... })
Unlike vue-Router, vuex is not instantiated, but vue.store. What does this mean, that Vuex itself contains the store constructor and install method, that Vuex should have the following basic structure
mystore/myvuex.js
let Vue
class Store{
constructor(){}}function install(_Vue) {}export default {Store,install}
Copy the code
Mount the $Store instance on the VUE component
As with VUE, adding store instances to vUE components can be done by blending in. (Because vue. use(Vuex) is executed first, the install method cannot get the store instance directly.) ,
/ /... class Store
function install(_Vue) {
Vue=_Vue
console.log(Vue)
Vue.mixin({
beforeCreate() {
// At this point, the context is already the component instance
// If this is the root instance, its $options will have a store instance
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
// Then you can get $store in the component}}}); }Copy the code
Reactive data state
You need to define reactive data state in the Store class, so that $store.state can be used in the component, and the page can be updated when state changes
let Vue
class Store{
constructor(options){
// Save options
this.$options=options;
const state=this.$options.state || {};
// Define reactive data $$state
Vue.util.defineReactive(this."$$state", state);
}
// Expose state
get state() {return this.$$state
}
set state(v) {console.error('please use replaceState to reset state'); }}Copy the code
Implement commit and Dispatch methods
Post all the code here
let Vue
class Store{
constructor(options){
// Save mutations and actions
this._mutations = options.mutations
this._actions = options.actions
this.$options=options;
const state=this.$options.state || {};
Vue.util.defineReactive(this."$$state", state);
// We can bind this to the current store instance to avoid problems with the direction of this
this.commit = this.commit.bind(this)
this.dispatch=this.dispatch.bind(this)}commit(type,payload){
// Find the user-defined mutation method based on type
const entry = this._mutations[type];
if(entry){
entry(this.state,payload)
}
}
dispatch(type,payload){
const entry = this._actions[type];
console.log(`entry`, entry);
if (entry) {
entry(this, payload); }}get state() {return this.$$state
}
set state(v) {console.error('please use replaceState to reset state'); }}function install(_Vue) {
Vue=_Vue
Vue.mixin({
beforeCreate() {
// At this point, the context is already the component instance
// If this is the root instance, its $options will have a store instance
if (this.$options.store) {
Vue.prototype.$store = this.$options.store; }}}); }export default { Store, install };
Copy the code
Finished, the basic function of Vuex has been realized, isn’t it very simple, we can try it together