手写一个简易版的 vuex(支持 state,getters,mutations,actions)

简介:vuex 相信大家都用过,内部到底是如何实现的呢,我根据源码以及一些参考资料,手写了一个简易版的 vuex,供大家参考。

本文github 源码地址

下面是实现步骤

1.项目依赖:(先安装,步骤略)
package.json

1
{
2
  "name": "vue-my-vuex",
3
  "version": "0.1.0",
4
  "private": true,
5
  "scripts": {
6
    "serve": "vue-cli-service serve",
7
    "build": "vue-cli-service build",
8
    "lint": "vue-cli-service lint"
9
  },
10
  "dependencies": {
11
    "core-js": "^3.6.4",
12
    "vue": "^2.6.11",
13
    "vuex": "^3.1.3"
14
  },
15
  "devDependencies": {
16
    "@vue/cli-plugin-babel": "~4.3.0",
17
    "@vue/cli-plugin-eslint": "~4.3.0",
18
    "@vue/cli-plugin-vuex": "^4.3.1",
19
    "@vue/cli-service": "~4.3.0",
20
    "babel-eslint": "^10.1.0",
21
    "eslint": "^6.7.2",
22
    "eslint-plugin-vue": "^6.2.2",
23
    "vue-template-compiler": "^2.6.11"
24
  }
25
}

2.项目目录结构
在这里插入图片描述
3.核心代码
/src/store/Vuex.js

1
export let Vue
2
function install(_Vue) {
3
  Vue = _Vue
4
5
  Vue.mixin({
6
    beforeCreate() {
7
      // 在vue原型上注册$store
8
      if (this.$options.store) {
9
        Vue.prototype.$store = this.$options.store
10
      }
11
    }
12
  })
13
}
14
15
class Store {
16
  constructor(options) {
17
    this.$option = options
18
19
    // 使用vue实例使state响应式
20
    this.state = new Vue({
21
      data: options.state
22
    })
23
24
    // 保存options里的mutations,actions
25
    this.mutations = options.mutations || {}
26
    this.actions = options.actions || {}
27
28
    // 实现getters
29
    this.getters = {}
30
    // 使getters响应式
31
    Object.keys(options.getters).forEach(key => {
32
      Object.defineProperty(this.getters, key, {
33
        get: () => {
34
           return options.getters[key](this.state)
35
        },
36
        enumerable: true
37
      })
38
    })
39
  }
40
41
  // 实现commit方法
42
  commit(type, pyload) {
43
    this.mutations[type](this.state, pyload)
44
  }
45
46
  // 实现dispatch方法
47
  dispatch(type, pyload) {
48
    this.actions[type](
49
      {
50
        state: this.state,
51
        commit: this.commit.bind(this)
52
      },
53
      pyload
54
    )
55
  }
56
}
57
58
export default { Store, install }
59
/**
60
 * 这样导出 相当于
61
 * const Vuex={Store,install}
62
 * export default  Vuex
63
 *
64
 *之所以这样导出 是因为使用的时候是 new Vuex.Store()
65
 */

/src/App.vue

1
<template>
2
  <div id="app">
3
    <h1>App 组件</h1>
4
    <div>计数:{{ $store.state.count }}个</div>
5
    <div>getters计数:{{ $store.getters.count }}个</div>
6
    <button @click="add">commit加</button>
7
    <button @click="dispatchAdd">dispatch加</button>
8
9
    <HelloWorld msg="Welcome to Your Vue.js App" />
10
  </div>
11
</template>
12
13
<script>
14
import HelloWorld from './components/HelloWorld.vue'
15
16
export default {
17
  name: 'App',
18
  components: {
19
    HelloWorld
20
  },
21
  methods: {
22
    add() {
23
      this.$store.commit('ADD_COUNT', 100)
24
    },
25
    dispatchAdd() {
26
      this.$store.dispatch('addCount', 1)
27
    }
28
  }
29
}
30
</script>
31
32
<style>
33
#app {
34
  font-family: Avenir, Helvetica, Arial, sans-serif;
35
  -webkit-font-smoothing: antialiased;
36
  -moz-osx-font-smoothing: grayscale;
37
  text-align: center;
38
  color: #2c3e50;
39
  margin-top: 60px;
40
}
41
</style>

/src/components/HelloWorld.vue

1
<template>
2
  <div class="hello">
3
    <h1>HelloWorld 组件</h1>
4
    {{ $store.state.count }}
5
  </div>
6
</template>
7
8
<script>
9
export default {
10
  name: 'HelloWorld',
11
  props: {
12
    msg: String
13
  }
14
}
15
</script>

4.实现效果
在这里插入图片描述

参考链接

1.https://github.com/vuejs/vuex

2.https://github.com/57code/vue-study