一、展示数据(state)
1. plugins/Vuex.js:
let Vue;
class Store {
constructor(options) {
// 1. 保存数据 通过 vue 中的 data 是响应式
this._vm = new Vue({
data: {
$$state: options.state
},
})
}
// 代理(设置访问器的方式来限制访问)
get state() {
return this._vm._data.$$state;
}
}
// 定义一个install方法
function install(_Vue) {
Vue = _Vue;
// 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
Vue.mixin({
beforeCreate() {
// 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
if (this.$options.store) {
// 将store 挂载到原型上
Vue.prototype.$store = this.$options.store;
}
}
})
}
export default { Store, install }
- 通过vue中data是响应式的原理,将options.state放进$$state中进行响应式。
- 设置get访问器限制访问,返回出this._vm._data.$$state;
2. store/index.js:
import Vue from 'vue';
import Vuex from '../plugins/vuex'
Vue.use( Vuex );
const store = new Vuex.Store({
state: {
num: 100
},
})
export default store;
3. App.vue:
<template>
<div>
{{ $store.state.num }}
</div>
</template>
二、修改数据(mutations和actions):
1. plugins/Vuex.js:
let Vue;
class Store {
constructor(options) {
// 1. 保存选项 将 store 文件中的 mutations 和 actions 获取到并赋值
this._mutations = options.mutations || {};
this._actions = options.actions || {};
// 2. commit dispatch 绑定this
this.commit = this.commit.bind(this)
this.dispatch = this.dispatch.bind(this)
// 保存数据
this._vm = new Vue({
data: {
$$state: options.state
},
})
}
// 代理(设置访问器的方式来限制访问)
get state() {
return this._vm._data.$$state;
}
// 3. mutations 和 actions 部分
commit(type, payload) {
// 通过 this._mutations[type] 获取到具体的 函数
const entry = this._mutations[type];
// 当前这个函数存在的话 就进行执行
entry && entry(this.state, payload)
}
dispatch(type, payload) {
// 通过 this._actions[type] 获取到具体的 异步函数
const entry = this._actions[type];
// 这个异步函数存在的话 那么就执行
entry && entry(this, payload)
}
}
// 定义一个install方法
function install(_Vue) {
Vue = _Vue;
// 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
Vue.mixin({
beforeCreate() {
// 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
// console.log(this.$options.store);
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
}
}
})
}
export default { Store, install }
- 首先将传递的mutations和actions绑定到store中
- 绑定commit和dispatch的this指向
- 通过commit方法的type类型,来找出_mutations中的方法,进行执行。
- commit的方法 entry需要传递this.state(state)和payload参数,dispatch方法需要传递上下文this(ctx)
2. store/index.js:
import Vue from 'vue';
import Vuex from '../plugins/vuex'
Vue.use( Vuex );
const store = new Vuex.Store({
state: {
num: 100
},
mutations: {
addNum(state,val) {
state.num += val;
}
},
actions: {
addAsyncNum(ctx, val) {
setInterval(()=>{
ctx.commit('addNum',val)
},2000)
}
},
})
export default store;
3. App.vue:
<template>
<div>
store中的数据为------{{ $store.state.num}}
<button @click="$store.commit('addNum',10)">++</button>
<button @click="$store.dispatch('addAsyncNum', 20)">Async ++</button>
</div>
</template>
三、getters方法的实现
1. plugins/Vuex.js:
let Vue;
class Store {
constructor(options) {
// 1. 保存选项
this.wrappedGetters = options.getters || {}
// 2. 定义 computed 和 getters 属性
const computed = {} // 获取到计算成功的数据 挂载到 store._vm上
this.getters = {} // 为自身提供一个getters方法 方便展示 计算结果
// 3. 绑定 this 指向
const store = this; // 获取到 this
// 4. 遍历 this.wrappedGetters 的所有的 key 值
Object.keys(this.wrappedGetters).forEach(key => {
// 5. 根据key值 获取到所对应的方法
const fn = store.wrappedGetters[key];
// 6. 以 key 为键, 方法为 值, 添加到 computed 中
computed[key] = () => {
return fn(store.state)
}
// 7. 为 this.getters 添加一个键值对,键是key(fil),
// 添加了一个展示方法 返回的是 store中的一个计算属性,键名是key(fil)
// 访问时 调用 getters.fil
Object.defineProperty(store.getters, key, {
get() {
return store._vm[key]
}
})
})
// 保存数据
this._vm = new Vue({
data: {
$$state: options.state
},
// 8. 将 computed 挂载到 原型上
computed
})
}
// 代理(设置访问器的方式来限制访问)
get state() {
return this._vm._data.$$state;
}
}
// 定义一个install方法
function install(_Vue) {
Vue = _Vue;
// 通过vue混入的方式,将下面的延迟到vue实例创建完毕以后执行
Vue.mixin({
beforeCreate() {
// 如果$options上面有store这个属性,咱们才去执行。避免不必要的渲染
// console.log(this.$options.store);
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
}
}
})
}
export default { Store, install }
- 获取传递的getters参数,保存在store中
- 定义computed,将计算成功的数据挂载到store._vm上
- 定义getters,展示数据时调用。
- 遍历所有的this.wapperGetters,获取到所有的key
- 根据key获取到对应的方法,将键值的形式添加到computed中,computed挂载到this._vm上
- 通过Object.defineProperty将方法添加到getters中,设置get方法,返回计算后的结果。
2. store/index.js:
import Vue from 'vue';
import Vuex from '../plugins/vuex'
Vue.use( Vuex );
const store = new Vuex.Store({
state: {
num: 100
},
getters: {
fil(state) {
return state.num * 2
}
}
})
export default store;
3. App.vue:
<template>
<div>
store中的数据为----{{ $store.getters.fil }}
</div>
</template>
<script>
export default {
}
</script>
手捏vuex