vuex简单实现

121 阅读1分钟

目标:

  1. store中存储的数据是响应式的
  2. mutations功能实现
  3. actions功能实现
  4. getters功能实现

拆分目标一:添加install和Store

  1. 添加install方法。
  2. install方法中,通过混入的方式,拿到store,挂载$store
  3. 添加Store,store中传入的state,mutations,actions,getters处理
  4. 添加commit,dispatch方法
// index.js
import { Store, install } from './store';
export default {
    Store,
    install
}
// store.js
let Vue;

export class Store {
    constructor(options = {}) {
        this._mutations = options.mutations || {};
        this._actions = options.actions || {};
        this._getters = getters || {};
        // 处理state
        resetStoreVM(this, options.state)
    }
    
    commit(type) {}
    
    dispatch(type) {}
}

export function install(_Vue) {
    Vue = _Vue;
    
    Vue.mixin({
        beforeCreate() {
            if (this.$options.store) {
                Vue.property.$store = this.$options.store;
            }
        }
    })
}

拆分目标二:store中存储的数据是响应式的

  1. 响应式数据使用new Vue()方式处理
  2. 外部不能通过$store.state的方式直接修改数据。
// store.js
export class Store {
    get state() {
        return this._vm._data.$$state;
    }
    set state(newState) {
        console.error('can not replace store state.');
    }
}

function resetStoreVM(store, state) {
    store._vm = new Vue({
        data() {
            return {
                $$state: state
            }
        }
    })
}

拆分目标三:mutations功能和actions功能实现

// store.js
commit(type, payload) {
    const entry = this._mutations[type];
    if (!entry) {
        console.error(`unknown mutation type: ${type}`);
        return;
    }
    entry(this._vm._data.$$state, payload)
}
    
dispatch(type, payload) {
    const entry = this._actions[type];
    if (!entry) {
        console.error(`unknown action type: ${type}`);
        return;
    }
    entry(this, payload)
}

拆分目标四:getters功能实现

function resetStoreVM(store, state) {
    const computed = {};
    store.getters = {};
    Object.keys(store._getters).forEach(key => {
        computed[key] = () => {
            return store._getters[key](store._vm._data.$$state)
        }
        Object.defineProperty(store.getters, key, {
            get: () => store._vm[key]
        })
    })
    
    store._vm = new Vue({
        data() {
            return {
                $$state: state
            }
        },
        computed
    })
}