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)`
    ]),
}
相關文章
相關標籤/搜索