首先我们先看下vuex的使用方式一般都是下面这样的
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count:0
},
mutations: {
changeCount (state,num) {
state.count += num
}
},
actions: {
changeCount (context,num) {
setTimeout(()=>{
context.commit('changeCount',num)
},2000)
}
},
getters: {
doubleCount (state){
return state.count*2
}
}
})
有个组件是这样的
<template>
<div>
<div>数量--{{$store.state.count}}</div>
<div>双倍数量--{{$store.getters.doubleCount}}</div>
<button @click="handleClick">点击加1</button>
<button @click="deferHandleClick">点击延迟加2</button>
</div>
</template>
<script>
export default {
name: 'Home',
methods:{
handleClick () {
this.$store.commit('changeCount',1)
},
deferHandleClick () {
this.$store.dispatch('changeCount',2)
}
}
}
</script>
我们要实现一个vuex主要有几个要点
- vuex是一个插件,通过Vue.use使用
- vuex里面有一个store类
- 实现state,mutations,actions,getters
- state改变的时候 通知组件数据变更
首先vuex是这样使用的
vuex里面有一个Store类,然后知道vuex是一个插件,通过Vue.use使用。
那么我们新建一个kVuex.js,代码里面应该有个Store类和一个install方法,大概是这样的
class Store {
}
function install(_vue) { // install方法接受一个vue的形参
}
export default {Store,install}
我们的main.js是这样的 把引入的store挂载到了vue根组件上
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import store from './store'
Vue.config.productionTip = false
new Vue({
router,
store,
render: h => h(App)
}).$mount('#app')
所以我们的install方法是这样的
let Vue;
class Store {
}
function install(_vue) {// 接受一个参数 是vue
Vue = _vue // 这里我们保存一下vue 一会还要用
Vue.mixin({ // Vue构造器注入beforeCreate方法
beforeCreate() {
if(this.$options.store){ // 因为在上面代码中store只挂载到了根组件 所以下面的代码只在根组件执行
Vue.prototype.$store = this.$options.store
}
}
})
}
export default {Store,install}
现在我们开始实现state,要知道我们的state是响应式的,state发生变化的时候,组件会发生变化
let Vue;
class Store {
constructor (options){
this.state = new Vue({ // 利用vue的数据响应式原理 这也是为什么vuex只能在vue里用的原因
data:{
state:options.state
}
})
}
}
function install(_vue) {
Vue = _vue
Vue.mixin({
beforeCreate() {
if(this.$options.store){
Vue.prototype.$store = this.$options.store
}
}
})
}
export default {Store,install}
实现mutations我们只需要加个映射就可以,但是我们是通过commit调用的,所以我们要实现commit方法
let Vue;
class Store {
constructor (options){
this.state = new Vue({ // 利用vue的数据响应式原理
data:options.state
})
this.mutations = options.mutations;//传进来的mutations
}
commit = (type,arg)=>{ // commit方法接受一个类型和参数 类型就是你调用的时候传的方法名
// 在组件里我们是这样用的this.$store.commit('changeCount',1)
this.mutations[type](this.state,arg) // 执行mutations里面的方法
}
}
function install(_vue) {
Vue = _vue
Vue.mixin({
beforeCreate() {
if(this.$options.store){
Vue.prototype.$store = this.$options.store
}
}
})
}
export default {Store,install}
实现actions一样也是加个映射关系。但是我们还要实现dispatch方法
let Vue;
class Store {
constructor (options){
this.state = new Vue({ // 利用vue的数据响应式原理
data:options.state
})
this.mutations = options.mutations;//传进来的mutations
this.actions = options.actions;//传进来的actions
}
commit = (type,arg)=>{ // commit方法接受一个类型和参数 类型就是你调用的时候传的方法名
// 在组件里我们是这样用的this.$store.commit('changeCount',1)
this.mutations[type](this.state,arg) // 执行mutations里面的方法
}
dispatch (type,arg) {// dispatch方法接受一个类型和参数 类型就是你调用的时候传的方法名
this.actions[type]({
commit:this.commit
},arg)
}
}
function install(_vue) {// 接受一个参数 是vue
Vue = _vue // 这里我们保存一下vue 一会还要用
Vue.mixin({ // Vue构造器注入beforeCreate方法
beforeCreate() {
if(this.$options.store){ // 因为在上面代码中store只挂载到了根组件 所以下面的代码只在根组件执行
Vue.prototype.$store = this.$options.store
}
}
})
}
export default {Store,install}
实现getters 就不能简单的加个映射了
let Vue;
class Store {
constructor (options){
this.state = new Vue({ // 利用vue的数据响应式原理
data:options.state
})
this.mutations = options.mutations;//传进来的mutations
this.actions = options.actions;//传进来的actions
this.getters = {}; //添加getters为{}
options.getters && this.handleGetter(options.getters) // 当传入的getters存在的话 执行handleGetter
}
commit = (type,arg)=>{ // commit方法接受一个类型和参数 类型就是你调用的时候传的方法名
// 在组件里我们是这样用的this.$store.commit('changeCount',1)
this.mutations[type](this.state,arg) // 执行mutations里面的方法
}
dispatch (type,arg) {// dispatch方法接受一个类型和参数 类型就是你调用的时候传的方法名
// 在组件里我们是这样用的this.$store.dispatch('changeCount',2)
this.actions[type]({ // 执行actions里面的方法
commit:this.commit
},arg)
}
handleGetter (getters){
Object.keys(getters).forEach(key=>{ // 拿出getters的key做一个循环
Object.defineProperty(this.getters,key,{ // 给this.getter添加属性,属性名为key这个变量,并添加get方法
get: ()=> {
return getters[key](this.state) // 执行getters里面的方法传参 并return出去
}
})
})
}
}
function install(_vue) {// 接受一个参数 是vue
Vue = _vue // 这里我们保存一下vue 一会还要用
Vue.mixin({ // Vue构造器注入beforeCreate方法
beforeCreate() {
if(this.$options.store){ // 因为在上面代码中store只挂载到了根组件 所以下面的代码只在根组件执行
Vue.prototype.$store = this.$options.store
}
}
})
}
export default {Store,install}
到此我们这个简单的vuex就完成了