store/index.js
import Vue from 'vue'
import Vuex from '../demoTools/kvuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
mutations: {
addState(state) {
state.count++
}
},
actions: {
actionsAddState({ commit }) {
setTimeout(() => {
commit('addState')
}, 500)
}
},
getters: {
getcount(state) {
return state.count + 10
}
}
})
Vue.use(Vuex)代码分析
Vue.use其实就是调用install函数 并传入vue的实例作为参数
function install(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {
// store属性是Vue实例化带来
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
export default { Store, install }
state的实现:使用vue的实例 能给实时拿到最新的数据,将数据进行返回
// 方式二 使用get隐藏一下state
this.vm = new Vue({
data: {
$$state: options.state
},
computed
})
get state() {
// $$state两个$不会被代理
return this.vm._data.$$state
}
set state(v) {
console.error('不允许修改state')
}
commit 和 dispatch的实现
class Store {
constructor(options) {
// 解决commit和dispatch两个方法的this指向的问题
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
// 实现commit方法
commit(type, payload) {
// commitEntry获取传入的函数
const commitEntry = this.mutations[type]
// 不存在函数名称
if (!commitEntry) {
console.log('不存在mutation')
}
// 调用函数并传入state和
commitEntry(this.state, payload)
}
// 实现dispatch方法
dispatch(type, payload) {
// commitEntry获取传入的函数
const dispatchEntry = this.actions[type]
// 不存在函数名称
if (!dispatchEntry) {
console.log('不存在action')
}
// 调用函数并传入this 可以结构出{{commit}}
dispatchEntry(this, payload)
}
}
}
getters的实现
class Store {
constructor(options) {
// vuex的getters的实现
this.curentGetters = options.getters
const computed = {}
this.getters = {}
const store = this
Object.keys(this.curentGetters).forEach(key => {
const fnc = store.curentGetters[key]
// 转为computed形式
// 将state状态通过函数返回
computed[key] = function() {
return fnc(store.state)
}
// getters只能读取 不能写入
Object.defineProperty(store.getters, key, {
// vm是前面的vue的实例
// vm所有数据都会被代理 所以所有的getters方法或者属性最终都可以在vm身上访问
get: () => store.vm[key]
})
})
// 挂载在vm实例
this.vm = new Vue({
data: {
$$state: options.state
},
computed
})
}
}
vuex实现源码以上综合
/* vuex的自定义实现
*/
let Vue
class Store {
constructor(options) {
// mutations和actions对象用来获取到身上对应的方法并进行触发
this.mutations = options.mutations
this.actions = options.actions
// vuex的getters的实现
this.curentGetters = options.getters
const computed = {}
this.getters = {}
const store = this
Object.keys(this.curentGetters).forEach(key => {
const fnc = store.curentGetters[key]
// 转为computed形式
// 将state状态通过函数返回
computed[key] = function() {
return fnc(store.state)
}
// getters只能读取 不能写入
Object.defineProperty(store.getters, key, {
// vm是前面的vue的实例
// vm所有数据都会被代理 所以所有的getters方法或者属性最终都可以在vm身上访问
get: () => store.vm[key]
})
})
// data的响应式 考虑到可以多个定义响应式
// 这里不使用defineReactiv单个定义响应式
// 使用Vue的响应系统data绑定
/* 方式一:this.state = new Vue({
data: options.state
}) */
// 方式二 使用get隐藏一下state
this.vm = new Vue({
data: {
$$state: options.state
},
computed
})
// 解决commit和dispatch两个方法的this指向的问题
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
get state() {
// $$state两个$不会被代理
return this.vm._data.$$state
}
set state(v) {
console.error('不允许修改state')
}
// 实现commit方法
commit(type, payload) {
// commitEntry获取传入的函数
const commitEntry = this.mutations[type]
// 不存在函数名称
if (!commitEntry) {
console.log('不存在mutation')
}
// 调用函数并传入state和
commitEntry(this.state, payload)
}
// 实现dispatch方法
dispatch(type, payload) {
// commitEntry获取传入的函数
const dispatchEntry = this.actions[type]
// 不存在函数名称
if (!dispatchEntry) {
console.log('不存在action')
}
// 调用函数并传入this 可以结构出{{commit}}
dispatchEntry(this, payload)
}
}
// Vue.use调用install方法
// install.call(this,{this,...})
function install(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {
// store属性是Vue实例化带来
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
export default { Store, install }