Vue 3.x 简单实现一个自己的 vue Store
plugins/store/index.js
let Vue
class Store {
constructor (options = {}) {
// this.vm = new Vue({
// data: {
// $state: options.state, // 以$开头的属性不会被 vm 直接访问到(vm.$state === undefined)
// },
// })
this._state = options.state || {}
this._getters = options.getters || {}
this._mutations = options.mutations || {}
this._actions = options.actions || {}
this.getters = {}
const store = this
Object.keys(this._getters).forEach(key => {
Object.defineProperty(this.getters, key, {
get () {
return store._getters[key](store.state, store.getters)
},
enumerable: true,
})
})
// 绑定 commit 上下⽂否则 action 中调⽤commit 时可能出问题!!
// 同时也把 action 绑了,因为 action 可以互调
const { commit, dispatch } = store
this.commit = function (...arg) {
commit.apply(store, arg)
}
this.dispatch = function (...arg) {
dispatch.apply(store, arg)
}
}
get state () {
// return this.vm._data.$state // (vm._data 等同于 vm.$data)
return Vue.observable(this._state)
}
set state (v) {
console.error('please use replaceState to reset state')
}
commit (type, payload) {
const mutationType = this._mutations[type]
if (!mutationType) {
console.error(`unknown mutation type ${type}`)
return
}
mutationType(this.state, payload)
}
dispatch (type, payload) {
const actionType = this._actions[type]
if (!actionType) {
console.error(`unknown action type ${type}`)
}
actionType({
state: this.state,
commit: this.commit,
}, payload)
}
}
function install (_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate () {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
},
})
}
export default {
Store,
install,
}
store/index.js
import Vue from 'vue'
import Vuex from '@/plugins/store/index.js'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 1,
},
getters: {
doubleCounter (state) {
return state.count * 2
},
},
mutations: {
addCount (state, payload) {
state.count += payload
},
},
actions: {
addCountAsync ({ state, commit }, payload) {
setTimeout(() => {
commit('addCount', state.count + payload)
}, 3000)
},
},
})
main.js
import Vue from 'vue'
import App from './App.vue'
import store from './store'
Vue.config.productionTip = false
new Vue({
store,
render: h => h(App),
}).$mount('#app')
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

下一篇: TypeScript 常见问题
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论