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

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

本文github 源码地址

下面是实现步骤

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

{
  "name": "vue-my-vuex",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.4",
    "vue": "^2.6.11",
    "vuex": "^3.1.3"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.3.0",
    "@vue/cli-plugin-eslint": "~4.3.0",
    "@vue/cli-plugin-vuex": "^4.3.1",
    "@vue/cli-service": "~4.3.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
  }
}

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

export let Vue
function install(_Vue) {
  Vue = _Vue

  Vue.mixin({
    beforeCreate() {
      // 在vue原型上注册$store
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

class Store {
  constructor(options) {
    this.$option = options

    // 使用vue实例使state响应式
    this.state = new Vue({
      data: options.state
    })

    // 保存options里的mutations,actions
    this.mutations = options.mutations || {}
    this.actions = options.actions || {}

    // 实现getters
    this.getters = {}
    // 使getters响应式
    Object.keys(options.getters).forEach(key => {
      Object.defineProperty(this.getters, key, {
        get: () => {
          return options.getters[key](this.state)
        },
        enumerable: true
      })
    })
  }

  // 实现commit方法
  commit(type, pyload) {
    this.mutations[type](this.state, pyload)
  }

  // 实现dispatch方法
  dispatch(type, pyload) {
    this.actions[type](
      {
        state: this.state,
        commit: this.commit.bind(this)
      },
      pyload
    )
  }
}

export default { Store, install }
/**
 * 这样导出 相当于
 * const Vuex={Store,install}
 * export default  Vuex
 *
 *之所以这样导出 是因为使用的时候是 new Vuex.Store()
 */

/src/App.vue

<template>
  <div id="app">
    <h1>App 组件</h1>
    <div>计数:{{ $store.state.count }}个</div>
    <div>getters计数:{{ $store.getters.count }}个</div>
    <button @click="add">commit加</button>
    <button @click="dispatchAdd">dispatch加</button>

    <HelloWorld msg="Welcome to Your Vue.js App" />
  </div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
  name: 'App',
  components: {
    HelloWorld
  },
  methods: {
    add() {
      this.$store.commit('ADD_COUNT', 100)
    },
    dispatchAdd() {
      this.$store.dispatch('addCount', 1)
    }
  }
}
</script>

<style>
#app {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

/src/components/HelloWorld.vue

<template>
  <div class="hello">
    <h1>HelloWorld 组件</h1>
    {{ $store.state.count }}
  </div>
</template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  }
}
</script>


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

参考链接

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

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

Logo

前往低代码交流专区

更多推荐