这是我的一篇学习笔记,内容中可能会存在一些写的或者理解的不太ok的地方,希望大家在发现时能不吝赐教,大家一起交流沟通,共同进步,噢耶!
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
这个状态自管理应用包含以下几个部分:
1、使用vue-cli创建一个test项目
2、安装vuex
vue add vuex
Vue.js 的插件应该暴露一个 install
方法。这个方法的第一个参数是 Vue
构造器,第二个参数是一个可选的选项对象:
MyPlugin.install = function (Vue, options) {
// 1. 添加全局方法或 property
Vue.myGlobalMethod = function () {
// 逻辑...
}
// 2. 添加全局资源
Vue.directive('my-directive', {
bind (el, binding, vnode, oldVnode) {
// 逻辑...
}
...
})
// 3. 注入组件选项
Vue.mixin({
created: function () {
// 逻辑...
}
...
})
// 4. 添加实例方法
Vue.prototype.$myMethod = function (methodOptions) {
// 逻辑...
}
}
let Vue;
class Store {
constructor(options) {
// data响应式处理
// this.$store.state.xx
// 将state中的属性隐藏起来,让用户不能直接访问到,而是通过get方法来读取
// vuex中的所有属性都是依赖于state的,我们只需要将state设置为响应式的数据即可
// 这里也可以通过Vue.util.defineReactive设置为响应式数据,但源码中使用的是new Vue方式
this._vm = new Vue({
data: {
$$state: options.state
}
})
// 保存用户配置
this._mutations = options.mutations || {}
this._actions = options.actions || {}
// 在这里必须改变this的指向,否则在store中使用时this会是undefined
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
// defineProperty(this.getters, 'doubleCounter', {get(){}})
// getters相当于state的计算属性,在页面上也是直接展示的,所以也需要做成响应式数据
this._getters = options.getters || {}
this.getters = {}
Object.keys(this._getters).forEach(name=>{
Object.defineProperty(this.getters,name,{
get:()=>{
return this._getters[name](this.state)
}
})
})
}
get state() {
return this._vm._data.$$state
}
set state(v) {
console.error('你不能直接修改state中的属性');
}
commit(funName, params) {
// 获取funName对应的mutation
const fun = this._mutations[funName]
if (!fun) {
console.error(`找不到${funName}方法`);
}
fun(this.state, params)
}
dispatch(funName, params) {
const fun = this._actions[funName]
if (!fun) {
console.error(`找不到${funName}方法`);
}
fun(this, params)
}
}
function install(_Vue) {
Vue = _Vue
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store
}
}
})
}
export default { Store, install };
let Vue;
class Store {
constructor(options = {}) {
// 将state中的属性隐藏起来,让用户不能直接访问到,而是通过get方法来读取
// vuex中的所有属性都是依赖于state的,我们只需要将state设置为响应式的数据即可
// 这里也可以通过Vue.util.defineReactive设置为响应式数据,但源码中使用的是new Vue方式
this._vm = new Vue({
data: {
$$state:options.state
}
});
}
get state() {
return this._vm._data.$$state
}
set state(v) {
console.error('你不能直接修改state中的属性');
}
}
function install(_Vue) {
Vue = _Vue;
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
}
}
});
}
export default { Store, install };
class Store {
constructor(options = {}) {
// 保存⽤户配置的mutations选项
this._mutations = options.mutations || {}
// 在这里必须改变this的指向,否则在store中使用时this会是undefined
this.commit = this.commit.bind(this)
}
commit(funName, params) {
// 获取funName对应的mutation
const fun = this._mutations[funName]
if (!params) {
console.error(`找不到${funName}方法`);
return
}
fun(this.state, params);
}
}
class Store {
constructor(options = {}) {
// 保存⽤户配置的actions选项
this._actions = options.actions || {}
// 在这里必须改变this的指向,否则在store中使用时this会是undefined
this.dispatch= this.dispatch.bind(this)
}
dispatch(funName, params) {
const fun = this._actions[funName]
if (!fun) {
console.error(`找不到${funName}方法`);
}
fun(this, params)
}
}
getters不同于commit和dispach,getters相当于vuex的计算属性
class Store {
constructor(options = {}) {
// vue2.0中的响应式实现是通过Object.defineProperty
// defineProperty(this.getters, 'doubleCounter', {get(){}})
this._getters = options.getters || {}
this.getters = {}
Object.keys(this._getters).forEach(name=>{
Object.defineProperty(this.getters,name,{
get:()=>{
return this._getters[name](this.state)
}
})
})
}
}