面试官:如何自己手写一个mini的vuex3?

介绍

说来惭愧,这对于喜欢摸鱼的程序员来说,vue3都发布这么久了,现在才开始阅读vuex3源码,现在分享一下个人对这次学习的总结,写的不好请大家轻喷。

地址

源码地址:vuejs/vuex@3.6.2

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 注册

使用classstatic属性进行创建一个名为install的静态方法, 用于Vue.use注册插件。

插件注册时把当前环境的vue对象引用保存下来,确保项目和插件使用的是同一个引用对象。因为需要利用项目中的data功能来辅助stategetters值更新后触发视图更新。

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: registerStateregisterGetters会在后面的实例属性里讲到)

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].mutationsmoduels.[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).
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值