Vuex基本使用的總結

Vuex 背後的基本思想: 把組件的共享狀態抽取出來,以一個全局單例模式管理,在這種模式下,咱們的組件樹構成了一個巨大的「視圖」,無論在樹的哪一個位置,任何組件都能獲取狀態或者觸發行爲!javascript

另外,經過定義和隔離狀態管理中的各類概念並強制遵照必定的規則,咱們的代碼將會變得更結構化且易維護。css

特色: html

  1. Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得高效更新。vue

  2. 你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用java

vuex

使用

在 Vue 的單頁面應用中使用,須要使用Vue.use(Vuex)調用插件。
使用很是簡單,只須要將其注入到Vue根實例中。vuex

import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
  state: {
    count: 0
  },
getter: {
    doneTodos: (state, getters) => {
      return state.todos.filter(todo => todo.done)
    }
  },
  mutations: {
    increment (state, payload) {
      state.count++
    }
  },
actions: {
  addCount(context) {
    // 能夠包含異步操做
    // context 是一個與 store 實例具備相同方法和屬性的 context 對象
  }
}
})
// 注入到根實例
new Vue({
  el: '#app',
  store,
  template: '<App/>',
  components: { App }
})複製代碼

而後改變狀態:數組

this.$store.commit('increment')複製代碼

Vuex 主要有四部分:promise

  1. state:包含了store中存儲的各個狀態。
  2. getter: 相似於 Vue 中的計算屬性,根據其餘 getter 或 state 計算返回值。
  3. mutation: 一組方法,是改變store中狀態的執行者。
  4. action: 一組方法,其中能夠含有異步操做

state

Vuex 使用 state來存儲應用中須要共享的狀態。爲了能讓 Vue 組件在 state更改後也隨着更改,須要基於state建立計算屬性。bash

const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count  // count 爲某個狀態
    }
  }
}複製代碼

getters

相似於 Vue 中的 計算屬性,能夠在因此來的其餘 state或者 getter改變後自動改變。
每一個getter方法接受 state和其餘getters做爲前兩個參數app

getters: {
    doneTodos: (state, getters) => {
      return state.todos.filter(todo => todo.done)
    }
  }複製代碼

mutations

前面兩個都是狀態值自己,mutations纔是改變狀態的執行者。mutations用於同步地更改狀態

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}複製代碼

其中,第一個參數是state,後面的其餘參數是發起mutation時傳入的參數。

this.$store.commit('increment', 10)複製代碼

commit方法的第一個參數是要發起的mutation名稱,後面的參數均當作額外數據傳入mutation定義的方法中。
規範的發起mutation的方式以下:

store.commit({
  type: 'increment',
  amount: 10   //這是額外的參數
})複製代碼

額外的參數會封裝進一個對象,做爲第二個參數傳入mutation定義的方法中。

mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}複製代碼

actions

想要異步地更改狀態,須要使用actionaction並不直接改變state,而是發起mutation

actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment')
    }, 1000)
  }
}複製代碼

發起action的方法形式和發起mutation同樣,只是換了個名字dispatch

// 以對象形式分發
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})複製代碼

action處理異步的正確使用方式

想要使用action處理異步工做很簡單,只須要將異步操做放到action中執行(如上面代碼中的setTimeout)。
要想在異步操做完成後繼續進行相應的流程操做,有兩種方式:

  1. action返回一個 promise
    dispatch方法的本質也就是返回相應的action的執行結果。因此dispatch也返回一個promise
store.dispatch('actionA').then(() => {
// ...
})
複製代碼
  1. 利用async/await。代碼更加簡潔。
// 假設 getData() 和 getOtherData() 返回的是 Promise

actions: {
  async actionA ({ commit }) {
    commit('gotData', await getData())
  },
  async actionB ({ dispatch, commit }) {
    await dispatch('actionA') // 等待 actionA 完成
    commit('gotOtherData', await getOtherData())
  }
}複製代碼

各個功能與 Vue 組件結合

stategetter結合進組件須要使用計算屬性

computed: {
    count () {
      return this.$store.state.count 
      // 或者 return this.$store.getter.count2
    }
  }
複製代碼

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'

// ....
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)`
    ]),
}複製代碼

將 store分割爲模塊。

能夠將應用的store分割爲小模塊,每一個模塊也都擁有全部的東西:state, getters, mutations, actions
首先建立子模塊的文件:

// initial state
const state = {
  added: [],
  checkoutStatus: null
}
// getters
const getters = {
  checkoutStatus: state => state.checkoutStatus
}
// actions
const actions = {
  checkout ({ commit, state }, products) {
  }
}
// mutations
const mutations = {
  mutation1 (state, { id }) {
  }
}
export default {
  state,
  getters,
  actions,
  mutations
}
複製代碼

而後在總模塊中引入:

import Vuex from 'vuex'
import products from './modules/products' //引入子模塊

Vue.use(Vuex)
export default new Vuex.Store({
  modules: {
    products   // 添加進模塊中
  }
})
複製代碼

其實還存在命名空間的概念,大型應用會使用。須要時查看文檔便可。Vuex的基本使用大體如此。

參考

https://www.jianshu.com/p/aae7fee46c36

https://vuex.vuejs.org/zh/guide/modules.html

相關文章
相關標籤/搜索