Alexis374/tech_post

vuex 文档总结

Alexis374 opened this issue · 0 comments

半翻译,半总结

读vuex文档


vuex是为了方便大型项目中多组件之间的状态管理而引入的插件,借鉴了Flux和Redux的架构模式。
整个app的状态都集中于store,store与简单的js对象相比有两点不同:

  1. 它是响应式的,store更改会自动反映到关联的组件,更新其显示
  2. 不能显式设定store的状态,而需要通过分发mutations。这使得每次更改都可以被追踪记录。

store的构成: state对象和mutations对象

import Vuex from 'vuex'

const state = {
  count: 0
}

const mutations = {
  INCREMENT (state) {
    state.count++
  }
}

export default new Vuex.Store({
  state,
  mutations
})

vuex的工作流:

用户交互触发action,action dispatch 相应类型的mutaion,
mutation修改state。getter函数抽取state当中需要的部分,组件调用相应的getter展示需要的数据。

action函数接受一个store对象作为第一个参数,但是也可以传入对象,vuex会自动包装。

export const incrementCounter = function ({ dispatch, state }) {
  dispatch('INCREMENT', 1)
}

mutations

  1. mutations 作为store的属性,是一个对象,是name和handler function的集合。handler接收state作为第一个参数
  2. name一般为大写,handler函数不可直接调用,只能通过store.dispatch(name,...restArgs)调用
  3. handler可以接收多个参数
  4. object-style dispath: store.dispatch({type:name,args}),对象作为handler的第二个参数
  5. mutation遵循vue的响应规则,推荐初始化时设置所有的值,当给对象添加属性时,应该用Vue.set(obj, 'newProp', 123)
    或使用es6语法state.obj = { ...state.obj, newProp: 123 }
  6. 推荐使用常量,作为mutation的name。在声明handler时可以用es6语法
mutations: {
    // we can use the ES2015 computed property name feature
    // to use a constant as the function name
    [SOME_MUTATION] (state) {
      // mutate state
    }
  1. mutation handler中的内容必须是同步的,因为异步函数无法确保函数何时调用,导致追踪状态困难。
  2. 业务中有异步的操作,应该写到action中,这也是为什么需要在把修改state的操作分成两个action和mutation。

actions

  1. action也是函数,接收store作为第一个参数,使用es6的argument destructuring,可以写成这样:
function incrementBy ({ dispatch }, amount) {
  dispatch('INCREMENT', amount)
}
  1. action的作用仅仅是dispatch mutation,不能返回值或者给action传递回调

  2. 在组件中使用时,可以在声明组件配置项中指定action,这样可以作为vm实例的方法,也可以应用在模板中。并且这样
    不用显式传递state对象。

    import { incrementBy } from './actions'
    
    const vm = new Vue({
      vuex: {
        getters: { ... },
        actions: {
          plus: incrementBy // bind using a different name
        }
      }
    })
    //可以应用为 vm.plus
    
    //bind all
    import * as actions from './actions'
    
    const vm = new Vue({
      vuex: {
        getters: { ... },
        actions // bind all actions
      }
    })