zoukankan      html  css  js  c++  java
  • 手写自己的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
    
    
  • 相关阅读:
    java中equals和==的区别 (转)
    LoadRunner常见问题整理(转)
    python 遇到 syntaxerror: non-ascii character '/xd6' in file 我 教你解决 (python问题)(转)
    Linux查看系统性能命令
    android权限大全
    StringTokenizer类的使用
    web_reg_find()查询信息为变量
    Loadrunner执行Java脚本
    LoadRunner调用Java程序—性能测试
    Request Connection: Remote Server @ 192.229.145.200:80
  • 原文地址:https://www.cnblogs.com/alaner/p/15331909.html
Copyright © 2011-2022 走看看