介绍
说来惭愧,这对于喜欢摸鱼的程序员来说,vue3都发布这么久了,现在才开始阅读vuex3源码,现在分享一下个人对这次学习的总结,写的不好请大家轻喷。
地址
myGithub:2460392754/mini-vuex3
项目结构
src
├── core
│ ├── helpers.ts
│ ├── index.ts
│ └── store.ts
├── types
│ └── index.ts
├── utils
│ ├── index.ts
│ ├── isModuleType.ts
│ ├── reactive.ts
│ └── register.ts
└── index.ts
实现
1 基本
1.1 注册
使用class
的static
属性进行创建一个名为install
的静态方法, 用于Vue.use
注册插件。
插件注册时把当前环境的vue
对象引用保存下来,确保项目和插件使用的是同一个引用对象。因为需要利用项目中的data
功能来辅助state
和getters
值更新后触发视图更新。
github: mini-vuex3/src/core/store.ts#L6-L23
import type {
VueConstructor } from 'vue';
// 保存当前vue引用, 确保和项目使用相同的引用
let _vue: VueConstructor;
export class store {
/**
* 插件注册
* @param vue
*/
static install(vue: VueConstructor) {
_vue = vue;
}
// do something...
}
1.2 实例化
通过class
的构造函数进行初始化。
(Tips: registerState
和registerGetters
会在后面的实例属性里讲到)
github: mini-vuex3/src/core/store.ts#L40-L59
import type Vue from 'vue';
import type {
StoreOpts } from '../types';
// 保存当前vue引用, 确保和项目使用相同的引用
let _vue: VueConstructor;
export class store {
private _vm: Vue = null;
private _mutations = null;
private _actions = null;
private _modules = null;
getters = null;
constructor(opts: StoreOpts) {
// 添加 原型属性,指向当前store实例化后的对象
_vue.prototype.$store = this;
// _state对象 响应式处理, 需要通知项目视图更新
this._vm = new _vue({
data() {
return {
_state: registerState(opts),
};
},
});
this.getters = registerGetters(this.state, opts || {
});
this._mutations = opts.mutations || {
};
this._actions = opts.actions || {
};
this._modules = opts.modules || {
};
registerModules(this._mutations, this._actions, this._modules);
}
}
registerModules
使用 es6 中Reflect
特性进行修改对象的键名模拟私有对象, 例如: { A: 'a' }
=> { _A: 'a' }
。
把规范化后moduels.[NAME].mutations
和moduels.[NAME].actions
对象进行合并。
github: mini-vuex3/src/utils/register.ts#L57-L84
/**
* 注册 modules
*/
export function registerModules(mutations: Mutations, actions: Actions, modules: Modules) {
Object.keys(modules).forEach((key) => {
const module = modules[key] as Module & {
_actions: Actions;
_mutations: Mutations;
};
// 修改键名
Reflect.set(module, '_actions', module.actions);
Reflect.set(module, '_mutations', module.mutations);
Reflect.deleteProperty(module, 'actions');
Reflect.deleteProperty(module, 'mutations');
let moduleActions = module._actions;
let moduleMutations = module._mutations;
if (module.namespaced === true) {
moduleMutations = setModuleNameDataKey(module.name, moduleMutations);
moduleActions = setModuleNameDataKey(module.name, moduleActions);
}
Object.assign(mutations, moduleMutations);
Object.assign(actions, moduleActions);
});
}
/**
* 修改 modules 中对象的键名, 使用 module.name 追加拼接
* @param moduleName
* @param data
* @returns
*/
function setModuleNameDataKey(moduleName: string, data: {
[key: string]: Function }) {
const res = {
};
Object.keys(data).