├── README.md └── mini-vuex.js /README.md: -------------------------------------------------------------------------------- 1 | # mini-vuex 2 | 和mini-vue配套使用的状态管理模式 3 | 4 | 5 | ### 支持以下选项 6 | * state 7 | * getters 8 | * mutations 9 | * actions 10 | * plugins 11 | 12 | 不支持模块 具体用法请参考[vuex官方文档](https://vuex.vuejs.org/zh/) 13 | 14 | ### 使用方法 15 | ``` 16 | 17 | 18 | ``` 19 | 示例 20 | ``` 21 |
22 | 23 | const store = new MiniVuex.Store({ 24 | state: { 25 | count: 1 26 | } 27 | }) 28 | 29 | const vm = new MiniVue({ 30 | el: '#app', 31 | store, 32 | }) 33 | ``` 34 | -------------------------------------------------------------------------------- /mini-vuex.js: -------------------------------------------------------------------------------- 1 | (function(root) { 2 | function Store(options = {}) { 3 | const self = this 4 | if (root.MiniVue) { 5 | install(root.MiniVue) 6 | } 7 | 8 | let plugins = options.plugins? options.plugins : [] 9 | let state = options.state? options.state : {} 10 | 11 | this._actions = Object.create(null) 12 | this._mutations = Object.create(null) 13 | this._wrappedGetters = Object.create(null) 14 | this._modules = new ModuleCollection(options) 15 | 16 | let store = this 17 | let dispatch = store.dispatch 18 | let commit = store.commit 19 | 20 | this.dispatch = function(type, payload) { 21 | return dispatch.call(store, type, payload) 22 | } 23 | this.commit = function(type, payload) { 24 | return commit.call(store, type, payload) 25 | } 26 | 27 | installModule(this, state, this._modules.root) 28 | resetStoreVM(this, state) 29 | plugins.forEach(plugin => plugin(self)) 30 | } 31 | 32 | Store.prototype = { 33 | commit(type, payload) { 34 | this._mutations[type].forEach(handler => { 35 | handler(payload) 36 | }) 37 | }, 38 | dispatch(type, payload) { 39 | if (typeof type === 'object' && type.type) { 40 | payload = type 41 | type = type.type 42 | } 43 | 44 | const entry = this._actions[type] 45 | return entry.length > 1 ? Promise.all(entry.map(handler => handler(payload))) : entry[0](payload) 46 | } 47 | } 48 | 49 | 50 | const prototypeAccessors = {state: {configurable: true}} 51 | 52 | prototypeAccessors.state.get = function() { 53 | return this._vm._data.$$state 54 | } 55 | 56 | prototypeAccessors.state.set = function() {} 57 | 58 | Object.defineProperties(Store.prototype, prototypeAccessors) 59 | 60 | function ModuleCollection(rawRootModule) { 61 | this.register([], rawRootModule, false) 62 | } 63 | 64 | ModuleCollection.prototype = { 65 | register(path, rawModule, runtime) { 66 | if (!runtime) { 67 | runtime = true 68 | } 69 | const newModule = new Module(rawModule, runtime) 70 | this.root = newModule 71 | } 72 | } 73 | 74 | 75 | function installModule(store, rootState, module) { 76 | let local = module.context = makeLocalContext(store) 77 | 78 | module.forEachMutation(function(mutation, key) { 79 | registerMutation(store, key, mutation, local) 80 | }) 81 | 82 | module.forEachAction(function(action, key) { 83 | let handler = action.handler || action 84 | registerAction(store, key, handler, local) 85 | }) 86 | 87 | module.forEachGetter(function(getter, key) { 88 | registerGetter(store, key, getter, local) 89 | }) 90 | } 91 | 92 | function Module(rawModule, runtime) { 93 | this.runtime = runtime 94 | this._children = Object.create(null) 95 | this._rawModule = rawModule 96 | const rawState = rawModule.state 97 | this.state = (typeof rawState === 'function' ? rawState() : rawState) || {} 98 | } 99 | 100 | Module.prototype.forEachGetter = function(fn) { 101 | if (this._rawModule.getters) { 102 | forEachValue(this._rawModule.getters, fn) 103 | } 104 | } 105 | 106 | Module.prototype.forEachAction = function(fn) { 107 | if (this._rawModule.actions) { 108 | forEachValue(this._rawModule.actions, fn); 109 | } 110 | } 111 | 112 | Module.prototype.forEachMutation = function(fn) { 113 | if (this._rawModule.mutations) { 114 | forEachValue(this._rawModule.mutations, fn) 115 | } 116 | } 117 | 118 | function forEachValue(obj, fn) { 119 | Object.keys(obj).forEach(function(key) {return fn(obj[key], key)}) 120 | } 121 | 122 | 123 | function makeLocalContext(store) { 124 | let local = { 125 | dispatch: store.dispatch, 126 | commit: store.commit 127 | } 128 | 129 | Object.defineProperties(local, { 130 | getters: { 131 | get() {return store.getters} 132 | }, 133 | state: { 134 | get() {return store.state} 135 | } 136 | }) 137 | return local 138 | } 139 | 140 | function registerMutation(store, type, handler, local) { 141 | let entry = store._mutations[type] || (store._mutations[type] = []) 142 | entry.push(function wrappedMutationHandler(payload) { 143 | handler.call(store, local.state, payload); 144 | }) 145 | } 146 | 147 | function registerAction(store, type, handler, local) { 148 | let entry = store._actions[type] || (store._actions[type] = []) 149 | entry.push(function wrappedActionHandler(payload, cb) { 150 | let res = handler.call(store, { 151 | dispatch: local.dispatch, 152 | commit: local.commit, 153 | getters: local.getters, 154 | state: local.state, 155 | rootGetters: store.getters, 156 | rootState: store.state 157 | }, payload, cb) 158 | return res 159 | }) 160 | } 161 | 162 | function registerGetter(store, type, rawGetter, local) { 163 | if (store._wrappedGetters[type]) { 164 | return 165 | } 166 | 167 | store._wrappedGetters[type] = function wrappedGetter(store) { 168 | return rawGetter( 169 | local.state, // local state 170 | local.getters, // local getters 171 | store.state, // root state 172 | store.getters // root getters 173 | ) 174 | } 175 | 176 | } 177 | 178 | function resetStoreVM(store, state, hot) { 179 | store.getters = {} 180 | let wrappedGetters = store._wrappedGetters 181 | let computed = {} 182 | 183 | forEachValue(wrappedGetters, (fn, key) => { 184 | computed[key] = () => fn(store) 185 | Object.defineProperty(store.getters, key, { 186 | get() { return store._vm[key]}, 187 | enumerable: true 188 | }) 189 | }) 190 | 191 | store._vm = new MiniVue({ 192 | data: { 193 | $$state: state 194 | }, 195 | computed: computed 196 | }) 197 | 198 | } 199 | 200 | let MiniVue 201 | 202 | function install(_MiniVue) { 203 | if (MiniVue && _MiniVue === MiniVue) { 204 | return 205 | } 206 | MiniVue = _MiniVue 207 | MiniVue.mixin({init: VuexInit}) 208 | } 209 | 210 | function VuexInit () { 211 | const options = this.$options 212 | if (options.store) { 213 | this.$store = typeof options.store === 'function'? options.store() : options.store 214 | } else if (options.parent && options.parent.$store) { 215 | this.$store = options.parent.$store 216 | } 217 | } 218 | 219 | const MiniVuex = { 220 | Store, 221 | install 222 | } 223 | 224 | root.MiniVuex = MiniVuex 225 | })(window) --------------------------------------------------------------------------------