vuex实现源码:
1、维护状态state
2、修改状态commit
3、业务逻辑控制dispatch
4、状态派发getters
5、实现state响应式
6、插件
7、混入
vux实现源码
kvuex.js:
let Vue;
//安装插件
function install(_Vue, storeNamr = "$store") {
Vue = _Vue;
//混入目的:把store选项指定到Vue原型上
Vue.mixin({
beforeCreate() {
if (this.$options.store) {
Vue.prototype.$store = this.$options.store;
}
}
})
}
class Store {
constructor(options = {}) {
//new Vue : 利用vue数据响应式
this.state = new Vue({
data: options.state
});
//初始化mutations
this.mutations = options.mutations || {};
this.actions = options.actions || {};
//getters配置项
console.log('options', options)
options.getters && this.handleGetters(options.getters);
}
//触发motations,实现commit
commit = (type, arg) => {
// this指向store实例
// this.mutations[type] 获取变更方法
this.mutations[type](this.state, arg);
}
dispatch(type, arg) {
const fn = this.actions[type];
fn({
commit: this.commit,
state: this.state
},
arg
)
}
//{getters:{score(state){return state.xx}}}
handleGetters(getters) {
console.log('getters', getters)
//getters是用户传递的对应规则
//this.getters是用户最终的值对象
this.getters = {}; //store实例上的getters
//Object.keys(getters) 将对象变成数组进行遍历
//定义只读属性
Object.keys(getters).forEach(key => {
Object.defineProperty(this.getters, key, {
//defineProperties 第三个参数是描述符,get函数只读
get: () => {
return getters[key](this.state);
}
})
})
}
}
export default { Store, install }
使用kvue
store/kindex.js
import Vue from "vue";
import KVuex from './kvuex';
Vue.use(KVuex)
//这里导出store的实例,又把store混入mixin Vue原型里,
//所以在页面上可以通过 this.$store[store实例]
export default new KVuex.Store({
state: {
count: 0
},
mutations: {
increment(state, n = 1) {
state.count += n;
}
},
//派生用法
getters: {
score() {
return '99999'
}
},
//actions做复杂的业务,类似controller
actions: {
//比如ajax请求
//commit,state上下文数据值
asynAdd({ commit }, n = 1) {
console.log('commit', commit)
return new Promise(resolve => {
setTimeout(() => {
commit('increment');
resolve({ ok: 1 })
}, 1000);
})
}
}
})
//main.js
```bash
import store from './store/kindex'
//指定路由器 store
new Vue({
store,
render: h => h(App)
}).$mount('#app')
页面使用
```bash
```bash
<template>
<div id="app">
<div>记录数据:{{$store.state.count}}</div>
<div>派生数据score:{{$store.getters.score}}</div>
<button @click="add">add</button>
<button @click="asynAdd">asynAdd</button>
</div>
</template>
<script>
export default {
methods: {
add() {
this.$store.commit("increment");
},
async asynAdd() {
const res = await this.$store.dispatch("asynAdd");
console.log("res", res);
}
}
};
</script>