vuex学习

最近接触的项目比较经常使用vuex,由于以前基本不涉及vuex的使用,这里作一下记录。
首先表达一下见解:vuex是主要是用到存放一些全局的变量,能够当作是全局式的响应变量,便于统一管理,因此比较适合存取数据字典。vue

Vuex的核心

State

包含了store中存储的各个状态
Vuex 使用state来存储应用中须要共享的状态。为了能让 Vue 组件在state更改后也随着更改,须要基于state建立计算属性。vuex

getter

相似于 Vue 中的计算属性,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被从新计算。
Getter 方法接受state做为其第一个参数:数组

const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    // 默认前两个参数
    doneTodos: (state, getters) => {
      return state.todos.filter(todo => todo.done)
    }
  }
})

Getter 会暴露为store.getters对象,能够以属性的形式访问这些值缓存

store.getters.doneTodos

注意:getter 在经过属性访问时是做为 Vue 的响应式系统的一部分缓存其中的。异步

mutation

一组方法,是改变store中状态的执行者,只能是同步操做函数

更改 Vuex 的 store 中的状态的惟一方法是提交 mutation。也就是说,前面两个都是状态值自己,mutations才是改变状态的执行者。
Vuex 中的 mutation 很是相似于事件:每一个 mutation 都有一个字符串的事件类型 (type)和 一个回调函数 (handler)。这个回调函数就是咱们实际进行状态更改的地方,而且它会接受 state 做为第一个参数:this

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state, n) {
      // 变动状态
      state.count += n
    }
  }
})
this.$store.commit('increment', 10)

规范的发起mutation的方式以下:spa

// 以载荷形式
store.commit('increment',{
  amount: 10   //这是额外的参数
})

// 或者使用对象风格的提交方式
store.commit({
  type: 'increment',
  amount: 10   //这是额外的参数
})

额外的参数会封装进一个对象,做为第二个参数传入mutation定义的方法中。code

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

注意:mutations只能是同步地更改状态。对象

Action

一组方法,含有异步操做的时候调用
想要异步地更改状态,就须要使用actionaction并不直接改变state,而是发起mutation
Action 函数接受一个与 store 实例具备相同方法和属性的 context 对象,所以你能够调用context.commit提交一个 mutation,或者经过context.statecontext.getters来获取 state 和 getters。

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}

Action与Mutation的区别

Action 相似于 mutation,不一样在于:

  • Action 提交的是 mutation,而不是直接变动状态。
  • Action 能够包含任意异步操做,而Mutation只能且必须是同步操做。

Module

因为使用单一状态树,应用的全部状态会集中到一个比较大的对象。当应用变得很是复杂时,store 对象就有可能变得至关臃肿。

这时咱们能够将 store 分割为模块(module),每一个模块拥有本身的stategettersmutationsactions、甚至是嵌套子模块——从上至下进行一样方式的分割。
代码示例:

const moduleA = {
  state: { ... },
  mutations: { ... },
  actions: { ... },
  getters: { ... }
}

const moduleB = {
  state: { ... },
  mutations: { ... },
  actions: { ... }
}

const store = new Vuex.Store({
  modules: {
    a: moduleA,
    b: moduleB
  }
})

store.state.a // -> moduleA 的状态
store.state.b // -> moduleB 的状态

各个模块与 Vue 组件结合

stategetter结合进组件须要使用计算属性

computed: {
    count () {
      return this.$store.state.count 
      // 或者 return this.$store.getter.count
    }
  }

mutationaction结合进组件须要在methods中调用this.$store.commit()或者this.$store.commit():

methods: {
    changeDate () {
        this.$store.commit('change');
    },
    changeDateAsync () {
        this.$store.commit('changeAsync');
    }
}

为了简便起见,Vuex 提供了四个辅助函数方法用来方便的将这些功能结合进组件。

  1. mapState
  2. mapGetters
  3. mapMutations
  4. mapActions

示例代码:

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'

export default {
    // ...
    computed: {
      localComputed () { /* ... */ },
        // 使用对象展开运算符将此对象混入外部对象中
      ...mapState({
        // 为了可以使用 `this` 获取局部状态,必须使用常规函数
        count(state) {
          return state.count + this.localCount
        }
      }),
      ...mapGetters({
        getterCount(state, getters) {
          return state.count + this.localCount
        }
      })
    }
    methods: {
      ...mapMutations({
          // 若是想将一个属性另取一个名字,使用如下形式。注意这是写在对象中
           add: 'increment' // 将 `this.add()` 映射为`this.$store.commit('increment')`
        }),
      ...mapActions({
          add: 'increment' // 将 `this.add()` 映射为 `this.$store.dispatch('increment')`
        })
    }
}

若是结合进组件以后不想改变名字,能够直接使用数组的方式。

methods: {
    ...mapActions([
      'increment', // 将 `this.increment()` 映射为 `this.$store.dispatch('increment')`

      // `mapActions` 也支持载荷:
      'incrementBy' // 将 `this.incrementBy(amount)` 映射为 `this.$store.dispatch('incrementBy', amount)`
    ]),
}
相关文章
相关标签/搜索