手写简单Vuex

Vuex

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

核心概念

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

状态 - state

state保存应用状态

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类,挂载$store Store具体实现:
创建响应式的state,
保存mutations、actions和getters 实现commit根据用户传入type执行对应mutation
实现dispatch根据用户传入type执行对应action,
同时传递上下文 实现getters,按照getters定义对state做派生
初始化:Store声明、install实现

let Vue;
class Store {
  constructor(options = {}) {
    this._vm = new Vue({
      data: {
        $$state:options.state
      }
}); }
  get state() {
    return this._vm._data.$$state
}
  set state(v) {
    console.error('please use replaceState to reset state');
} }
function install(_Vue) {
  Vue = _Vue;
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store;
} }
}); }
export default { Store, install };

实现commit:根据用户传入type获取并执行对应mutation

class Store {
 constructor(options = {}) {
// 保存用户配置的mutations选项
   this._mutations = options.mutations || {}
 }
commit(type, payload) {
// 获取type对应的mutation
const entry = this._mutations[type]
   if (!entry) {
     console.error(`unknown mutation type: ${type}`);
     return
}
// 指定上下文为Store实例
// 传递state给mutation entry(this.state, payload);
} }

实现actions:根据用户传入type获取并执行对应action

class Store {
  constructor(options = {}) {
// 保存用户编写的actions选项 this._actions = options.actions || {}
// 绑定commit上下文否则action中调用commit时可能出问题!! // 同时也把action绑了,因为action可以互调
const store = this
const {commit, action} = store
    this.commit = function boundCommit(type, payload) {
      commit.call(store, type, payload)
    }
    this.action = function boundAction(type, payload) {
      return action.call(store, type, payload)
    }
}
dispatch(type, payload) {
// 获取用户编写的type对应的action const entry = this._actions[type]
    if (!entry) {
      console.error(`unknown action type: ${type}`); 
return
}
// 异步结果处理常常需要返回Promise
    return entry(this, payload);
  }
}

实现getter,state的计算属性

let Vue;
class Store {
  constructor(options) {
    // 定义响应式的state
    // this.$store.state.xx
    // 借鸡生蛋
    let computed={}
    Object.keys(options.getters).forEach(function (key) { 
      computed[key]=function () {
        return options.getters[key](options.state)
      } 
    })
   console.log(computed)
 
    this._vm = new Vue({
      data: {
        $$state: options.state
      },
      computed:computed
    })
    
    this._mutations = options.mutations
    this._actions = options.actions

    // 绑定this指向
    this.commit = this.commit.bind(this)
    this.dispatch = this.dispatch.bind(this)
  }
  get getters() {
    return this._vm
  }
  // 只读
  get state() {
    return this._vm._data.$$state
  }

  set state(val) {
    console.error('不能直接赋值呀,请换别的方式!!天王盖地虎!!');
    
  }
  
  // 实现commit方法,可以修改state
  commit(type, payload) {
    // 拿出mutations中的处理函数执行它
    const entry = this._mutations[type]
    if (!entry) {
      console.error('未知mutaion类型');
      return
    }

    entry(this.state, payload)
  }

  dispatch(type, payload) {
    const entry = this._actions[type]

    if (!entry) {
      console.error('未知action类型');
      return
    }

    // 上下文可以传递当前store实例进去即可
    entry(this, payload)
  }
}

function install(_Vue){
  Vue = _Vue

  // 混入store实例
  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

// { Store, install }相当于Vuex
// 它必须实现install方法
export default { Store, install }
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容