vuex源码解析

vuex源码解析

首先我们先观察一下官方store实例的结构,然后再考虑按照它的结构实现一下

在这里插入图片描述

主要实现一个Store类和ModuleCollect类、以及helper辅助函数

Store类

// 1、插件:挂载$store
// 2、实现Store
// state的name与module名重复,state同名状态会被覆盖掉
import ModuleCollection from './ModuleCollection'
let Vue;
class Store {
    constructor(options) {
        // 所有的actions,包括子模块的actions
        // {string:Array<function>}
        this._mutations = {}
        // 所有的actions,包括子模块的actions
        // {string:Array<function>}
        this._actions = {}
        // 收集getters的初始容器,还没有实现响应式
        // {string:function}
        this._wrappedGetters = {}
        // 命名空间与module的映射
        // {string:module类}
        this._modulesNamespaceMap = {}
        // actions的插件订阅者
        this._actionSubscribers = {}
        // mutations的插件订阅者
        this._subscribes = []
        // getters
        this.getters = {} // 需要借助vue的计算属性
        // 把数据格式化成一个想要的树结构
        this._modules = new ModuleCollection(options)
        const state = this._modules.root.state
        // 递归将结果进行分类
        // this 整个store
        // this.state 当前的根状态
        // [] 为了递归来创建
        // this.module.root 从根模块进行安装
        installModule(this, state, [], this._modules.root)
        // 将state变为响应式,并且把getters变为计算属性
        resetStoreVm(this, state)
        // 处理插件
        options.plugins.forEach(plugin => plugin(this))
    }

    // 插件订阅mutations
    subscribe(fn) {
        this._subscribes.push(fn)
    }

    // 插件订阅actions
    subscribeActions(fn) {
        this._actionSubscribers.push(fn)
    }

    // 提交更改 会在当前的store上找到对应的函数执行
    // 采用箭头函数就不需要绑定this了
    commit = (mutationName, payload) => {
        this._mutations[mutationName].forEach(fn => fn(payload))
    }
    // dispatch对应的action在当前的store上找到对应的函数执行
    // 采用箭头函数就不需要绑定this了
    dispatch = (actionName, payload) => {
        this._actions[actionName].forEach(fn => fn(payload))
    }

    get state() {
        return this._vm._data.$$state
    }

    set state(val) {
        // 禁止用户直接改变state
        throw new Error('不允许改变,请使用replaceState')
    }

    replaceState(state) {
        this._vm._data.$$state = state
    }
}

const install = (_Vue) => {
    Vue = _Vue
    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) {
                Vue.prototype.$store = this.$options.store
            }
        },
    })
}

// 迭代对象,会将对象的key与value拿到
function forEach(obj, cb) {
    Object.keys(obj).forEach(key => {
        cb(key, obj[key])
    })
}
// 判断是否是对象
function isObject(obj) {
    return obj !== null && typeof obj == 'object'
}
// 统一参数
function unifyObjectStyle(type,
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值