手写自己的Vuex

Vue

Vue中最重要的就是数据驱动和组件化,每个组件都有自己的data,template,methods。

Vuex

进行状态管理,负责组件中的通信。
多个视图依赖同一状态;
来自不同视图的行为需要变更同一状态;

Vue的插件;

插件一般用来给Vue添加全局功能。

  1. 使用插件
    Vue.use(myPlugins),把插件注册到Vue上。该方法执行时,会触发插件的install方法初始化,并将Vue作为参数传入。
  2. 开发插件:
    vue.js的插件,有公开方法install,该方法的第一个参数是Vue的构造器,第二个是可选的选项对象。
    myPlugins.install=function(Vue,options){
    //...
    }

Vuex的使用:

1. 创建store.js文件

点击查看代码
- import Vue from 'vue';
- import Vuex from 'vuex';
- Vue.use(Vuex);
//结构
- const store= new Vuex.Store({
    state:{},
    getters:{},
    mutations:{},
    actions:{},
})
- export default store;

2. main.js文件中引入

import store from './store';
挂载到Vue实例中;
new Vue({
store,
render: (h) => h(App),
}).$mount('#app')

  • this.$store.xxx

Vuex插件的开发;

依赖于vue的双向数据绑定和插件系统;
首先必须有插件的install方法,
其次根据Vuex的结构可知Store是类。

  • class Store{
    constructor(options){

    },
    //...
    }
    function install(Vue){
    //...
    }
    export default {
    Store,
    install
    };

方法install的实现

Vue中加入参数store,但只有根组件有store,其他组件没有,需要让其他组件也有这个参数。
利用Vue.mixin()混入,将内容混入到Vue的初始参数。

点击查看代码
- function install(Vue) {
    Vue.mixin({
        beforeCreate() {//created时 options已经初始化完
            if (this.$options && this.$options.store) {//根组件
                this.$store = this.$options.store;
            } else { //子组件 C=A && B : A true->get B
                // 判定是子组件,就能直接拿到父组件的store? -- 父子组件执行顺序
                this.$store = this.$parent && this.$parent.store;

            }
        }
    })
}

父子组件执行顺序:

父、子组件执行顺序:
父beforeCreate-> 父created -> 父beforeMounte
-> 子beforeCreate ->子create ->子beforeMount ->子 mounted
-> 父mounted

类store的实现

基于以下

  • new Vuex.Store({
    state: {
    num:0,
    },
    getters:{
    getNum(state){
    //...
    }
    },
    mutations:{
    setNum(state,val){
    //...
    }

    },
    actions:{}
    })

  • state
    this.$store.state
    借助vue的数据是响应式的构造。new Vue()传入state的值。
    class Store{
    constructor(options){
    this.state=options.state||{};
    }
    }

  • getters
    this.$store.getters.
    Object.defineProperty();
    对类store中传入的options的getters的每个函数劫持。
    getters(state){

}

  • mutations 同步
    和getters实现方法一致。
    setNum(state,args){

}
调用时:

  • this.$store.commit(mutationName,args);
    构造commit方法。
  • actions 异步
    addNum(context,args){
    context.commit(xx);
    }
    或者解构
    addNum({commit},args){
    commit(args);
    }
  • this.$store.dispatch(actionName,args);
    mapGetters,mapMutations,mapActions。

扩展

Object.create();
双向数据绑定:
数据劫持和添加观察者。

代码实现

点击查看代码
let Vue
//myVuex.js
class Store {
    constructor(options) {
        this.vm = new Vue({
            data: {
                state: options.state
            }
        })

        let getters = options.getter || {}
        this.getters = {}
        Object.keys(getters).forEach(getterName => {
            Object.defineProperty(this.getters, getterName, {
                get: () => {
                    return getters[getterName](this.state)
                }
            })
        })

        let mutations = options.mutations || {}
        this.mutations = {}
        Object.keys(mutations).forEach(mutationName => {
            this.mutations[mutationName] = (arg) => {
                mutations[mutationName](this.state, arg)
            }
        })

        let actions = options.actions
        this.actions = {}
        Object.keys(actions).forEach(actionName => {
            this.actions[actionName] = (arg) => {
                actions[actionName](this, arg)
            }
        })

    }
    //dispatch,commit是方法;其余getter,state是属性!!!
    dispatch(method, arg) {
        this.actions[method](arg)
    }
    commit = (method, arg) => {
        console.log(method);
        console.log(this.mutations);
        this.mutations[method](arg)
    }
    get state() {
        return this.vm.state
    }
}
let install = function (vue) {
    Vue = vue
    Vue.mixin({
        beforeCreate() {
            //因为vue实例会加入store,$options的意思就是vue实例的参数
            //该步骤的目的是让this.$store能直接访问到
            if (this.$options && this.$options.store) {
                this.$store = this.$options.store
            } else {
                //let c= a && b; a为true则 c=b; ||时 相反
                this.$store = this.$parent && this.$parent.$store
            }
        }
    })
}

let Vuex = {
    Store,
    install
}

export default Vuex

原文地址:https://www.cnblogs.com/alaner/p/15331909.html