vuex的使用
store/index.js
import Vue from 'vue'
import KVuex from '../kvuex'
Vue.use(KVuex);
export default new KVuex.Store({
state: {
count: 0
},
mutations: {
add(state, num) {
state.count += num
}
},
getters: {
score: (state) => state.count + 2
},
actions: {
asyncAdd({ commit }) {
commit('add', 3)
}
}
})
main.js
import Vue from "vue";
import App from "./App.vue";
import store from './store'
Vue.config.productionTip = false;
Vue.prototype.$bus = new Vue();
new Vue({
store,
render: h => h(App)
}).$mount("#app");
组件内使用
<template>
<div>
<h3>vuex test</h3>
<p>{{$store.state.count}}</p>
<p>{{$store.getters.score}}</p>
<button @click="add">add</button>
<button @click="asyncAdd">asyncAdd</button>
</div>
</template>
<script>
export default {
name: 'VueStudyKvuextest',
data() {
return {
};
},
mounted() {
},
methods: {
add() {
this.$store.commit('add', 1)
},
asyncAdd() {
this.$store.dispatch('asyncAdd')
}
},
};
</script>
<style lang="scss" scoped>
</style>
vuex实现
定义Store类
vuex的实例$store会提供两个方法:commit和dispatch,所以在Store类内需要实现这两个方法,commi本质上是去调用mutation里面对应的方法,dispatch本质也是通过对应的actions再去调用mutation里面的方法,需要注意的是由于getters里面的属性都是只读的,所以需要单独处理为只读属性
class Store {
constructor(options = {}) {
//定义state,利用vue设置为响应式
this.state = new Vue({
data: options.state
})
//初始化mutation,用于commit调用
this.mutations = options.mutations || {}
//初始化actions
this.actions = options.actions || {}
options.getters && this.handleGetter(options.getters)
}
commit = (type, arg) => {
const fn = this.mutations[type]
fn(this.state, arg)
}
dispatch = (type, arg) => {
const fn = this.actions[type]
fn({ commit: this.commit, state: this.state }, arg)
}
handleGetter(getters) {
this.getters = {}
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](this.state)
})
})
}
}
export default { Store }
定义install方法
利用install方法里传入的vue对象,执行混入,判断如果是根组件的话就在beforeCreate生命周期里就在vue的prototype上挂载 $store
let Vue
function install(_vue) {
// 接受vue.use()时传进来的vue对象
Vue = _vue
//执行混入
Vue.mixin({
beforeCreate() {
// 判断当前组件选项中是否有store,有的话则为根组件
if (this.$options.store) {
//在Vue的protopyte上挂在$store,值为根组件上传入的store(本质是Vuex的实例对象)
Vue.prototype.$store = this.$options.store
}
},
});
}
完整代码
//定义install方法,执行混入,在vue原型上挂在$store
//创建 Store 类 ,
let Vue
function install(_vue) {
// 接受vue.use()时传进来的vue对象
Vue = _vue
//执行混入
Vue.mixin({
beforeCreate() {
// 判断当前组件选项中是否有store,有的话则为根组件
if (this.$options.store) {
//在Vue的protopyte上挂在$store,值为根组件上传入的store(本质是Vuex的实例对象)
Vue.prototype.$store = this.$options.store
}
},
});
}
class Store {
constructor(options = {}) {
//定义state,利用vue设置为响应式
this.state = new Vue({
data: options.state
})
//初始化mutation,用于commit调用
this.mutations = options.mutations || {}
//初始化actions
this.actions = options.actions || {}
options.getters && this.handleGetter(options.getters)
}
commit = (type, arg) => {
const fn = this.mutations[type]
fn(this.state, arg)
}
dispatch = (type, arg) => {
const fn = this.actions[type]
fn({ commit: this.commit, state: this.state }, arg)
}
handleGetter(getters) {
this.getters = {}
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get: () => getters[key](this.state)
})
})
}
}
export default { Store, install }