跳到主要内容

手写简易版 Vuex

简易版 Vuex,直接引入也可以用

let Vue  // 插件全局使用

class Store {
constructor(options) {
// 保存用户定义的 mutations,actions,getters
this._mutations = options.mutations
this._actions = options.actions
this._getters = options.getters


// 更正 this 指向
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)

// 实现 this.getters
const computed = {}
const store = this
this.getters = {}
for (let key in this._getters) {
// 用户定义的 getters 方法
const fn = store._getters[key]
// 无参数形式访问 this.getters.key
computed[key] = () => fn(store.state)
// 响应式只读属性
Object.defineProperty(this.getters, key, {
get: () => store._vm[key]
})
}

// Vue 默认会把 data 遍历处理成响应式
this._vm = new Vue({
data: {
$$state: options.state,
},
computed
})
}

// es6 get set
get state() {
return this._vm._data.$$state
}

set state(v) {
console.error('use replaceState to reset state')
}

commit(type, payload) {
const entry = this._mutations[type]
if (!entry) console.error('unknow mutations type')

entry(this.state, payload)
}

dispatch(type, payload) {
const entry = this._actions[type]
if (!entry) console.error('unknow actions type')

entry(this, payload)
}
}

// Vue.use 方式 install.apply(this,[this,...])
function install(_Vue) {
Vue = _Vue //保存参入的 Vue,不用引入也能使用

// 全局混入,挂载 $store,延迟下面逻辑到 store 被添加到 new vue 选项时才执行
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}

export default {Store, install}