前言
手动实现一个vuex,简单了解其原理
vuex的基本使用
// 1.Vue.use注册vuex
Vue.use(Vuex)
// 2.创建store实例
const store = new Vue.Store({
// 数据
state: {
counter: 0
},
// 自动计算,类似计算属性
getters: {
doubleCounter(state) {
return state.counter * 2
}
},
// 同步修改数据
mutations: {
add(state) {
state.counter++
}
},
// 异步
actions: {
add({commit}) {
setTimeout(()=>{
commit('add')
},1000)
}
},
})
// 3.传入Vue的options选项中
new Vue({
store,
// ...
})
// 4.在页面中使用
<template>
<div class="home">
<p @click="$store.commit('add')">counter: {{$store.state.counter}}</p>
<p @click="$store.dispatch('add')">async counter: {{$store.state.counter}}</p>
<p >getters counter: {{$store.getters.doubleCounter}}</p>
</div>
</template>
vuex实现
思路
- vuex在use之后,会在每个vue实例上,都存在$store方法,所以可以通过beforeCreate时,在原型上添加
- state上的数据都是响应式的,可以通过new Vue来实现
代码
let Vue
// 方法在use的时候会执行,参考上一篇文章
function install(_Vue) {
Vue = _Vue
Vue.minx({
beforeCreate() {
if(this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
class Store {
constructor(options) {
this.getters = {}
const computed = {}
Object.keys(options.getters).forEach(key=>{
// 封装计算属性,传入给vue实例
computed[key] = () => options.getters[key](this.state)
// 定义getters属性的get方法,访问该对象的属性时,就去访问vue的计算属性
Object.defineProperty(this.getters, key, {
get: () => this._vm[key],
enumerable: true // for local getters
})
})
this._vm = new Vue({
data: {
$$state: options.state
}
})
this._mutations = options.mutations
this._actions = options.actions
// 绑定this
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
// 执行mutations同步方法
commit(type, payload) {
const entry = this._mutations[type]
if(!entry) {
console.error('not function')
}
entry(this.state, payload)
}
// 执行actions异步方法
dispatch(type, payload) {
const entry = this._actions[type]
if(!entry) {
console.error('not function')
}
entry(this, payload)
}
get state() {
return this._vm._data.$$state
}
set state(v) {
console.error('not set')
}
}
export default {
install,
Store
}
最后
简易版的vuex算是完成,周末愉快。