03-Vuex数据管理

643 阅读1分钟

Vuex是什么

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。

vuex

Vuex核心概念

借用vue本身的数据响应式机制使state响应化,从而使state变化立刻响应在依赖的视图中

vuex与vue有强耦合,所以只能用于vue,这是跟redux最大的区别

1. State

状态、数据

2. Getter

可以认为是 store 的计算属性,就像计算属性一样,getter的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

3. Mutation

更改状态的函数

4. Action

  • Action 提交的是 mutation,而不是直接变更状态。
  • 异步操作

5. Module

Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块

Vuex实现的核心步骤

1. 实现插件

$store挂载,这样全局才能使用

2. 实现store类

解析Vuex配置(持有state,实现dispatch,commit、getters方法)

3. 实现数据响应式

借助vue实现数据响应式

Vuex源码解析

  • vuex插件实现
let Vue

class Store {
  constructor (options = {}) {
    // 让state数据成为响应式数据
    this.state = new Vue({ data: options.state })
    options.getters && this.handleGetters(options.getters)
    this.mutations = options.mutations || {}
    this.actions = options.actions || {}
    // 防止this丢失,此处bind一下
    this.commit = this.commit.bind(this)
    this.dispatch = this.dispatch.bind(this)
  }

  commit (type, payload) {
    this.mutations[type](this.state, payload)
  }

  dispatch (type, payload) {
    // this是store的实例,此处作为上下文传入action,能解构成{commit,state,getters}等
    return this.actions[type](this, payload)
  }

  handleGetters (getters) {
    this.getters = {}

    Object.keys(getters).forEach(key => {
      // 这些属性是只读的
      Object.defineProperty(this.getters, key, {
        get: () => {
          return getters[key](this.state)
        }
      })
    })
  }
}

function install (_vue) {
  Vue = _vue
  Vue.mixin({
    beforeCreate () {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default { Store, install }

注意导出方式的不同,使用的时候也会有一些不同

Object.defineProperty(obj, prop, desc):作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性。
1.obj 需要定义属性的当前对象
2.prop 当前需要定义的属性名
3.desc 属性描述符

  • 使用自己实现的vuex做测试
import Vue from 'vue'
import Vuex from '../mVuex'

Vue.use(Vuex)

export default new Vuex.Store({
  state: {
    count: 0
  },
  getters: {
    left (state) {
      return 100 - state.count
    }
  },
  mutations: {
    SET_COUNT (state, payload) {
      state.count += payload
    }
  },
  actions: {
    asyncIncrement ({ commit, getters }, payload) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (getters.left > 0) {
            commit('SET_COUNT', 10)
            resolve()
            return
          }
          reject(new Error('err'))
        }, 1000)
      })
    }
  },
  modules: {
  }
})

参考

Vuex

Vuex源码