Vuex实现

  • 新创建一个class类实现Vuex基本功能
  • 将store注入Vue实例和Vue组件中
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <div id="app">
    <span>{{num}}</span>
    <button @click='add'>增加1</button>
    <button @click='asyncAdd'>异步增加1</button>
    <Child />
  </div>
</body>
<script src="./vue.js"></script>
<script>
  // 实现Vuex
  class Store {
    constructor(options) {
      this.vm = new Vue({ // 实例化一个Vue对象,将 外面 Vuex的参数传进来
        data() {
          return { state: options.state } // 将 Vuex的参数 state 传进来,为的是实现数据的监听
        }
      })

      let getters = options.getters;
      this.getters = {}
      Object.keys(getters).forEach(getterName => {
        Object.defineProperty(this.getters, getterName, {
          get: () => {
            return getters[getterName](this.vm.state)
          }
        })
      })
      let mutations = options.mutations;
      this.mutations = {};
      Object.keys(mutations).forEach(mutationName => {
        this.mutations[mutationName] = (payload) => {
          mutations[mutationName](this.state, payload)
        }
      })
      let actions = options.actions;
      this.actions = {};
      Object.keys(actions).forEach(actionName => {
        this.actions[actionName] = (payload) => {
          actions[actionName].call(this, this, payload)
        }
      })
    }

    get state() {
      return this.vm.state;
    }

    commit(mutationName, payload) {
      this.mutations[mutationName](payload);
    }

    dispatch(actionName, payload) {
      this.actions[actionName](payload);
    }
  }

  // 实例化一个Vuex
  let store = new Store({
    state: { num: 1 },
    getters: {
      getNum: function (state) {
        return state.num
      }
    },
    mutations: {
      add(state, payload) {
        state.num = state.num + payload;
      }
    },
    actions: {
      asyncAdd({ commit }, payload) {
        setTimeout(() => {
          this.commit('add', payload)
        }, 3000)
      }
    }
  })

  //在Vue实例创建时插入Vue实例和Vue组件中
  Vue.mixin({
    beforeCreate() {
      if (this.$options && this.$options.store) {
        this.$store = this.$options.store;
      } else {
        this.$store = this.$parent && this.$parent.$store;
      }
    },
  })

  var Child = {
    template: '<h1>{{$store.state.num}}</h1>'
  }

  new Vue({
    el: '#app',
    components: { Child },
    computed: {
      num() {
        return this.$store.state.num
      }
    },
    store: store,
    methods: {
      add() {
        this.$store.commit('add', 1)
      },
      asyncAdd() {
        this.$store.dispatch('asyncAdd', 10)
      }
    },
    created() {
    }
  })
</script>

</html>

 

posted @ 2020-04-21 14:13  Merrys  阅读(216)  评论(0编辑  收藏  举报