Vuex是什么
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

Vuex核心概念
借用vue本身的数据响应式机制使state响应化,从而使state变化立刻响应在依赖的视图中
vuex与vue有强耦合,所以只能用于vue,这是跟redux最大的区别
1. State
状态、数据
2. Getter
可以认为是 store 的计算属性,就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。
3. Mutation
更改状态的函数
4. Action
- Action 提交的是 mutation,而不是直接变更状态。
- 异步操作
5. Module
Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块
Vuex实现的核心步骤
1. 实现插件
$store挂载,这样全局才能使用
2. 实现store类
解析Vuex配置(持有state,实现dispatch,commit、getters方法)
3. 实现数据响应式
借助vue实现数据响应式
Vuex源码解析
- vuex插件实现
let Vue
class Store {
constructor (options = {}) {
// 让state数据成为响应式数据
this.state = new Vue({ data: options.state })
options.getters && this.handleGetters(options.getters)
this.mutations = options.mutations || {}
this.actions = options.actions || {}
// 防止this丢失,此处bind一下
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
}
commit (type, payload) {
this.mutations[type](this.state, payload)
}
dispatch (type, payload) {
// this是store的实例,此处作为上下文传入action,能解构成{commit,state,getters}等
return this.actions[type](this, payload)
}
handleGetters (getters) {
this.getters = {}
Object.keys(getters).forEach(key => {
// 这些属性是只读的
Object.defineProperty(this.getters, key, {
get: () => {
return getters[key](this.state)
}
})
})
}
}
function install (_vue) {
Vue = _vue
Vue.mixin({
beforeCreate () {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
export default { Store, install }
注意导出方式的不同,使用的时候也会有一些不同
Object.defineProperty(obj, prop, desc):作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
1.obj 需要定义属性的当前对象
2.prop 当前需要定义的属性名
3.desc 属性描述符
- 使用自己实现的vuex做测试
import Vue from 'vue'
import Vuex from '../mVuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: {
count: 0
},
getters: {
left (state) {
return 100 - state.count
}
},
mutations: {
SET_COUNT (state, payload) {
state.count += payload
}
},
actions: {
asyncIncrement ({ commit, getters }, payload) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (getters.left > 0) {
commit('SET_COUNT', 10)
resolve()
return
}
reject(new Error('err'))
}, 1000)
})
}
},
modules: {
}
})