简介: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>
参考链接
1.https://github.com/vuejs/vuex
2.https://github.com/57code/vue-study