2020-01-03 Vuex设计原理及简单实现

2020-01-03 Vuex设计原理及简单实现

Vuex核心概念

Vuex是集中式存储管理应用的所有组件的状态,并以相应的规则保证以可预测的方式发生变化

vuex

安装插件:vue add vuex

组成部分:

  • state状态、数据
  • mutations更改状态的函数
  • actions异步操作
  • store包含以上概念的容器

状态-state
state保存应用状态,store.js

export default new Vuex.Store({
	state: {counter:0}
})

状态变更-mutations
mutations用于修改状态,store.js

export default new Vuex.Store({
	mutations:{
		add(state){
			state.counter++
		}
	}
})

派生状态-getters
从state派生出新状态,类似于计算属性

export default new Vuex.Store({
	getters:{
		doubleCounter(state){
		return state.counter*2
		}
	}
})

动作-actions
添加业务逻辑,类似于controller

export default new Vuex.Store({
	actions:{
		add({commit}){
			setTimeout(()=>{
				commit('add')
			},1000)
		}
	}
})

Vuex原理解析

问题分析:

实现插件:
一是实现Store类
有以下几点:
1、维持一个响应式状态state
2、实现commit()
3、实现dispatch()
4、实现类似于计算属性getters

二是挂载$store

/**
 * 1、声明一个插件
 * 2、实现一个Store
 * 实现响应式state属性
 * 实现两个方法commit()/dispatch()
 */
let Vue;

class Store {
  constructor(options) {
    // 1、保存选项
    this._mutations = options.mutations || {};
    this._actions = options.actions || {};

    // 2、做响应式状态的state属性
    // Vue.util.defineReactive(this, 'state', {})
    this._vm = new Vue({
      data: {
        $$state: options.state
      },
      computed: {
        getters() {
          return options.getters;
        }
      }
    });

    // 上下文对象绑定this
    this.commit = this.commit.bind(this);
    this.dispatch = this.dispatch.bind(this);

    // 实现getters
    // 1.动态设置getters属性
    // 2.响应式
    // 3.能否利用上vue的computed计算属性缓存
    this.initGetters = this.initGetters.bind(this);
  }

  // 给用户暴露接口
  get state() {
    // console.log(this._vm);
    // $data不是响应式,_data是响应式
    return this._vm._data.$$state;
  }

  set state(v) {
    console.error("please use replaceState to reset");
  }

  // getters
  get getters() {
    return this.initGetters();
  }

  set getters(v) {
    console.error("please use replaceGetters to reset");
  }

  // 执行getters里的函数,返回一个对象集合
  initGetters() {
    const newGetters = {};
    for (const key in this._vm.getters) {
      newGetters[key] = this._vm.getters[key](this.state);
    }
    return newGetters;
  }

  // store.commit(type, payload)
  commit(type, payload) {
    // 获取mutations
    const entry = this._mutations[type];
    if (!entry) console.error("unknown mutations type");

    entry(this.state, payload);
  }

  // store.dispatch(type, payload)
  dispatch(type, payload) {
    // 获取actions
    const entry = this._actions[type];
    if (!entry) console.error("unknown actions type");

    // {commit, dispatch, state, getters}
    entry(this, payload);
  }
}

function install(_Vue) {
  Vue = _Vue;

  // 挂载$store
  Vue.mixin({
    beforeCreate() {
      // 这里this指向组件实例,new Vue({store(参数)})
      if (this.$options.store) {
        // 给每个组件实例暴露store实例
        Vue.prototype.$store = this.options.store;
      }
    }
  });
}

// 导出对象相当于Vuex
export default { Store, install };

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值