简易vuex源码实现
kvuex.js 文件 (实现vuex插件)
// 1、维护状态state // 2、修改状态commit // 3、业务逻辑控制dispatch // 4、状态派发getter // 5、实现state响应式 // 6、插件 // 7、混入 let Vue function install(_Vue, storeName = '$store') { Vue = _Vue // 混入:把store选项指定到Vue原型上 Vue.mixin({ beforeCreate() { // 判断main.js的当期组件选择中,是否有sotre if(this.$options.store){ Vue.prototype[storeName] = this.$options.store } } }) } class Store { // options: { state: {count:0}, mutations:{count(state){}} } constructor(options = {}){ // 利用vue数据响应式 this.state = new Vue({ data: options.state }) // 初始化mutations this.mutations = options.mutations || {} this.actions = options.actions || {} options.getters && this.handleGetters(options.getters) } // 触发mutations,需要实现commit commit = (type, arg) => { // this只想Store实例 const fn = this.mutations[type] // 获取状态变更函数 fn(this.state, arg) } dispatch = (type, arg) => { const fn = this.actions[type] return fn({commit: this.commit, state: this.state}, arg) } // {getters: {score(state){return state.xx}}} handleGetters(getters){ this.getters = {} // store实例上的getters // 定义只读的属性 Object.keys(getters).forEach(key => { Object.defineProperty(this.getters, key, { get: () => { return getters[key](this.state) } }) }) } } export default {Store, install}
kindex.js 文件 相当于store.js文件
import Vue from 'vue' import KVuex from '../kvuex' Vue.use(KVuex) export default new KVuex.Store({ state: { count: 0 }, mutations: { add(state, num = 1) { state.count += num } }, getters: { // 相当于计算属性 score(state) { return 'score:' + state.count } }, actions: { // 处理复杂业务逻辑,类似于controller // 比如ajax请求 asyncAdd({ commit }) { // 参数解构,拿到上下文 setTimeout(() => { commit('add') }, 1000); } } })
测试文件---vue文件
<template> <div> <h3>vuex test</h3> <p>{{$store.state.count}}</p> <p>{{$store.getters.score}}</p> <button @click="add">add</button> <button @click="asyncAdd">asyncAdd</button> </div> </template> <script> export default { methods: { add() { this.$store.commit('add', 2) }, asyncAdd(){ this.$store.dispatch('asyncAdd') } }, } </script>