vuex 手撸原理

105 阅读3分钟

新建vuex.js

let Vue //vue的构造函数const forEach = (obj, callback) => {    Object.keys(obj).forEach((key) => {        callback(key, obj[key])    })}class ModuleCollection {    constructor(options) {        this.register([], options)    }    register(path, rootModule) {        let newModule = {            _row: rootModule,            _children: {},            state: rootModule.state,        }        if (path.length == 0) {            this.root = newModule        } else {            let parent = path.slice(0, -1).reduce((root, current) => {                return this.root._children[current]            }, this.root)            parent._children[path[path.length - 1]] = newModule        }        if (rootModule.modules) {            forEach(rootModule.modules, (moduleName, module) => {                this.register(path.concat(moduleName), module)            })        }    }}//需要递归树 将结果挂载 getters mutations  actionsconst installModule = (store, state, path, rootModule) => {    // 先处理跟模块的getters属性    if (path.length > 0) {        //子模块  把子模块的状态放到父模块上        let parent = path.slice(0, -1).reduce((state, current) => {            return state[current]        }, state)        Vue.set(parent, path[path.length - 1], rootModule.state)    }    let getters = rootModule._row.getters    if (getters) {        forEach(getters, (getterName, fn) => {            Object.defineProperty(store.getters, getterName, {                get: () => {                    return fn(rootModule.state)                },            })        })    }    let mutations = rootModule._row.mutations    if (mutations) {        forEach(mutations, (mutationName, fn) => {            let arr =                store.mutations[mutationName] || (store.mutations[mutationName] = [])            arr.push((payload) => {                fn(rootModule.state, payload)            })        })    }    let actions = rootModule._row.actions    if (actions) {        forEach(actions, (actionName, fn) => {            let arr = store.actions[actionName] || (store.actions[actionName] = [])            arr.push((payload) => {                fn(store, payload)            })        })    }    forEach(rootModule._children, (moduleName, module) => {        installModule(store, state, path.concat(moduleName), module)    })}class Store {    constructor(options) {            // this._vm = options.state            this._vm = new Vue({                data: {                    //observer                    state: options.state, //吧对象变成可以监控的对象                },            })            this.getters = {}            this.actions = {}            this.mutations = {}                // let getters = options.getters || {} //用户传递过了的getters                // this.getters = {}            //     // 吧getters属性定义到 this.getters中 并且根据状态的变化 重新执行此函数            // forEach(getters, (getterName, value) => {            //     Object.defineProperty(this.getters, getterName, {            //         get: () => {            //             return value(this.state)            //         },            //     })            // })            // let mutations = options.mutations || {}            // this.mutations = {}            // forEach(mutations, (mutationName, value) => {            //     // 先把用户传过来的mutation放到我们的estore实例上            //     this.mutations[mutationName] = (payload) => {            //         value(this.state, payload)            //     }            // })            // let actions = options.actions || {}            // this.actions = {}            // Object.keys(actions).forEach((actionName) => {            //     // 先把用户传过来的mutation放到我们的estore实例上            //     this.actions[actionName] = (payload) => {            //         actions[actionName](this, payload)            //     }            // })            //我需要先格式化一下当前用户传递来的数据            // let root = {            //     _raw: rootModule,            //     _children: {            //         a: {            //             _raw: rootModule,            //             _children: {},            //         },            //     },            // }            // 收集所有的模块            this.modules = new ModuleCollection(options)            console.log(this.modules)            //安装模块            installModule(this, this.state, [], this.modules.root)                // let modules = options.modules || {}        }        // dispatch = (type, payload) => {        //     this.actions[type](payload)        // }    dispatch = (type, payload) => {        this.actions[type].forEach((fn) => {            fn(payload)        })    }    commit = (type, payload) => {        //找到对应的action执行        this.mutations[type].forEach((fn) => {            fn(payload)        })    }    get state() {        console.log(this._vm.state)        return this._vm.state    }}// vue的组件渲染 先渲染父组件 在渲染子组件 深度优先function install(_Vue) {    Vue = _Vue    Vue.mixin({            beforeCreate() {                // 需要先判断是父组件还是子组件  如果是子组件 应该吧父组件的store增加给子组件                if (this.$options && this.$options.store) {                    //父组件                    this.$store = this.$options.store                } else {                    // 去父组件拿                    this.$store = this.$parent && this.$parent.$store                }            },        })        // 需要给每个自检都注册一个this.$store}export default { install, Store }

1.新建install 方法 暴露外界调用函数

function install(_Vue) {    Vue = _Vue    Vue.mixin({            beforeCreate() {                // 需要先判断是父组件还是子组件  如果是子组件 应该吧父组件的store增加给子组件                if (this.$options && this.$options.store) {                    //父组件                    this.$store = this.$options.store                } else {                    // 去父组件拿                    this.$store = this.$parent && this.$parent.$store                }            },        })        // 需要给每个自检都注册一个this.$store}

  1. 全局创建Vue,将_vue外界传递过来的全局化
  2. 创建Vuv.mixin() 使所以组件都能用到这下面的方法
  3. 创建beforeCreate函数,使所以组件在初始化前都能调用到,并且获取到store里面内容

2.创建Strore函数

在单个模块情况下代码

class Store {    constructor(options) {            // this._vm = options.state            this._vm = new Vue({                data: {                    //observer                    state: options.state, //吧对象变成可以监控的对象                },            })            this.getters = {}            this.actions = {}            this.mutations = {}                            let getters = options.getters || {} //用户传递过了的getters            this.getters = {}                // 吧getters属性定义到 this.getters中 并且根据状态的变化 重新执行此函数            forEach(getters, (getterName, value) => {                Object.defineProperty(this.getters, getterName, {                    get: () => {                        return value(this.state)                    },                })            })            let mutations = options.mutations || {}            this.mutations = {}            forEach(mutations, (mutationName, value) => {                // 先把用户传过来的mutation放到我们的estore实例上                this.mutations[mutationName] = (payload) => {                    value(this.state, payload)                }            })            let actions = options.actions || {}            this.actions = {}            Object.keys(actions).forEach((actionName) => {                // 先把用户传过来的mutation放到我们的estore实例上                this.actions[actionName] = (payload) => {                    actions[actionName](this, payload)                }            })            我需要先格式化一下当前用户传递来的数据            let root = {                _raw: rootModule,                _children: {                    a: {                        _raw: rootModule,                        _children: {},                    },                },            }        }        // dispatch = (type, payload) => {        //     this.actions[type](payload)        // }    dispatch = (type, payload) => {        this.actions[type].forEach((fn) => {            fn(payload)        })    }    commit = (type, payload) => {        //找到对应的action执行        this.mutations[type].forEach((fn) => {            fn(payload)        })    }    get state() {        console.log(this._vm.state)        return this._vm.state    }}