Vuex入門介紹

Vuex 是什麼?

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。html

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

https://www.jianshu.com/p/5624362cd1f4--出處vue

看完這段專業的解釋,我反正是一臉懵逼,心裏毫無波瀾,甚至有點想吃醬肘子。感受和沒說同樣嘛!keep going。es6

什麼是"狀態管理模式"?

一個簡單Vue計數器應用vuex

new Vue({
  // state
  data () {
    return {
      count: 0
    }
  },
  // view
  template: `
    <div>{{ count }}</div>
  `,
  // actions
  methods: {
    increment () {
      this.count++
    }
  }
})

這個狀態自管理應用包含如下幾個部分:api

  • state,驅動應用的數據源;
  • view,以聲明方式將 state 映射到視圖;
  • actions,響應在 view 上的用戶輸入致使的狀態變化。

這是一種「單向數據流」的理念。
而後說明一下這種理念的缺點,當咱們的應用遇到多個組件共享狀態時,單向數據流的簡潔性很容易被破壞:異步

    • 多個視圖依賴於同一狀態。
    • 來自不一樣視圖的行爲須要變動同一狀態。

這裏說的是,vue 組件之間的傳值操做,組件很少的狀況下,嵌套的父子組件(prop,emit,on)和兄弟組件(global event bus)還容易操做一些。可是若是項目龐大,組件結構複雜,組件間的數據傳遞會變得很困難,後期代碼不易維護。模塊化

看到這裏,貌似明白了些這鬼東西是要解決什麼問題了。好的,而後咱們繼續往「坑」裏走。函數

最簡單的store

每個 Vuex 應用的核心就是 store(倉庫)。「store」基本上就是一個容器,它包含着你的應用中大部分的狀態 (state)。Vuex 和單純的全局對象有如下兩點不一樣:工具

  • Vuex 的狀態存儲是響應式的。當 Vue 組件從 store 中讀取狀態的時候,若 store 中的狀態發生變化,那麼相應的組件也會相應地獲得高效更新。
  • 你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交 (commit) mutation。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以實現一些工具幫助咱們更好地瞭解咱們的應用。
// 若是在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex)

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  }
})

如今,你能夠經過 store.state 來獲取狀態對象,以及經過 store.commit 方法觸發狀態變動:this

store.commit('increment'); // 觸發修改變量的方法
console.log(store.state.count); // -> 1

WTF?這是啥,這不就是「全局變量」嘛!多個組件可能用到的數據,存儲到 store(倉庫)裏,可是這些數據是響應式的,因此對這些數據進行操做時,要遵照相應的規則。例如上面的例子。對 count 進行修改,要經過 commit 來觸發 mutation 裏的方法對數據進行操做。

 
好了,喝口個人枸杞大補茶壓壓驚 [ 微笑 ]。從這裏再往坑裏走,纔是 Vuex 的一些 核心概念,他們是:

 

  • State
  • Getter
  • Mutation
  • Action
  • Module

讓咱們開始吧。

State

Vuex 使用單一狀態樹,用一個對象就包含了所有的應用層級狀態。至此它便做爲一個「惟一數據源 (SSOT)」而存在。這也意味着,每一個應用將僅僅包含一個 store 實例。單一狀態樹讓咱們可以直接地定位任一特定的狀態片斷,在調試的過程當中也能輕易地取得整個當前應用狀態的快照。

這段話說的是一個 Vuex 只能包含一個store(存儲數據的庫),這樣你在訪問數據的時候好找些。
store 的其中一個配置項就是 state 。這個state吧,能夠把他比做成vue實例中的data選項,就是把數據放在這裏面。

const state = {
  // 商品列表
  shopList:[{
    id: 1,
    name: '蘭博基尼',
    price: 10
  },{
    id: 2,
    name: '五菱宏光',
    price: 99999
  }],
  // 購物車列表
  addList: []
};

new Vuex.Store({
  state, // 這裏是es6語法,至關於  state: state
  ...
});

獲取商品列表 this.$store.state.shopList 就能看到了,或者使用輔助函數mapState,這樣雖然方便簡單,建議新手先研究一下 es6 和方法原理,這裏不作解釋。

computed: mapState([
  // 映射 this.shopList爲 store.state.shopList
  'shopList'
])

Vuex 文檔中有不少 es6 語法,若是有還不瞭解的同窗們,可要抓緊上車嘍。

Getter

我一度懷疑是否是文檔寫錯了,少加了一個s。(Getters)
這一項從字面意思上就能夠看出,他是用來取數據獲得數據的。有人會問,爲何不直接用this.$store.state.shopList這種方式直接拿呢。這種方式確實能夠拿到,可是常常會有一些狀況是對拿到的數據作一些處理,例如格式化、過濾數據。。。這時候就會用到 Getter 了。

const getters = {
    // 獲取id爲2的商品
    shopid2(state){
        return state.shopList.find((el)=>{
            return el.id == 2;    
        });
    }
};

使用this.$store.getters.shopid2獲得五菱宏光,便可加入秋名山車神爭霸,走上人生巔峯。
輔助函數 mapGetters 方法:

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用對象展開運算符將 getter 混入 computed 對象中
    ...mapGetters([
      'shopid2'
      // ...
    ])
  }
}

Mutation

更改 Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數:

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    increment (state) {
      // 變動狀態
      state.count++
    }
  }
})

你須要以相應的 type 調用 store.commit 方法:this.$store.commit('increment')

你想要動個人數據,就得守我 Vuex 的規矩(順我者昌,逆我者亡)。
拿數據用 Getters ,改數據用 mutation 。這個 mutation 有點像 vue 的生命週期鉤子函數,裏面是一些方法,經過 this.$store.commit(typeName) 對應的函數名稱,觸發對應的函數。

提交載荷(Payload)

你能夠向 store.commit 傳入額外的參數,即 mutation 的 載荷(payload):

// ...
mutations: {
  increment (state, n) {
    state.count += n
  }
}
store.commit('increment', 10);


// 在大多數狀況下,載荷應該是一個對象,這樣能夠包含多個字段而且記錄的 mutation 會更易讀
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}
store.commit('increment', {
  amount: 10
})

 輔助函數 mapMutations 方法:

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    ...mapMutations([
      'increment', // 將 `this.increment()` 映射爲 `this.$store.commit('increment')`

      // `mapMutations` 也支持載荷:
      'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.commit('incrementBy', amount)`
    ]),
    ...mapMutations({
      add: 'increment' // 將 `this.add()` 映射爲 `this.$store.commit('increment')`
    })
  }
}

在 Vuex 中,mutation 都是同步事務:

store.commit('increment')
// 任何由 "increment" 致使的狀態變動都應該在此刻完成。

爲了處理異步操做,讓咱們繼續往下走 。

Action

Action 相似於 mutation,不一樣在於:

  • Action 提交的是 mutation,而不是直接變動狀態。
  • Action 能夠包含任意異步操做

也就是說,Action 執行的仍是 Mutation ,只不過他能夠異步執行,差很少就是給 Mutation 外邊包了一層函數。

乍一眼看上去感受畫蛇添足,咱們直接分發 mutation 豈不更方便?實際上並不是如此,還記得 mutation 必須同步執行這個限制麼?Action 就不受約束!咱們能夠在 action 內部執行異步操做:
actions: {
  incrementAsync ({ commit }) {
    setTimeout(() => {
      commit('increment'); // 在異步函數成功後調用 Mutation
    }, 1000)
  }
}

經過 this.$store.dispatch('incrementAsync')便可調用。
輔助函數 mapActions 方法

import { mapActions } from 'vuex'

export default {
  // ...
  methods: {
    ...mapActions([
      'increment', // 將 `this.increment()` 映射爲 `this.$store.dispatch('increment')`

      // `mapActions` 也支持載荷:
      'incrementBy' // 將 `this.incrementBy(amount)` 映射爲 `this.$store.dispatch('incrementBy', amount)`
    ]),
    ...mapActions({
      add: 'increment' // 將 `this.add()` 映射爲 `this.$store.dispatch('increment')`
    })
  }
}

Module

因爲使用單一狀態樹,應用的全部狀態會集中到一個比較大的對象。當應用變得很是複雜時,store 對象就有可能變得至關臃腫。
爲了解決以上問題,Vuex 容許咱們將 store 分割成模塊(module)。每一個模塊擁有本身的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進行一樣方式的分割:
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 的狀態
Module 的意思也不難理解,若是你有不少的狀態,都寫在一塊兒會比較亂,後邊也很差改,你就能夠給他們分個類,好比 moduleA 是個人購物車模塊的狀態管理,moduleB 是個人商品信息模塊的狀態管理。
對於大型應用,咱們會但願把 Vuex 相關代碼分割到模塊中。下面是項目結構示例:
├── index.html
├── main.js
├── api
│   └── ... # 抽取出API請求
├── components
│   ├── App.vue
│   └── ...
└── store
    ├── index.js          # 咱們組裝模塊並導出 store 的地方
    ├── actions.js        # 根級別的 action
    ├── mutations.js      # 根級別的 mutation
    └── modules
        ├── cart.js       # 購物車模塊
        └── products.js   # 產品模塊

何時用 Vuex?

這個嘛,很簡單。你以爲你的項目裏,各組件之間傳參什麼的,相處的很和諧,那就無所謂用不用了。
當你的組件兄弟們有傳參問題,有不少這個組件要用,那個組件要,其餘好幾個組件也要,要的你生不如死,你就能夠考慮一下了。

總結

最後,咱們再回顧一下 Vuex 都包含什麼,是作什麼用的。

store
俗稱倉庫,倉庫裏是你的模塊的數據、數據狀態、對數據作的操做,都在這個倉庫裏。

 state
倉庫裏的數據都放到這個裏面,很像 vue 的 data 。

 

getters
一般獲取能夠用 this.$store.state.shopList 就能夠拿到,可是若是你想對這項數據加工一下(格式化、過濾),就在 getters 裏處理,而後經過 this.$store.getters.eventName 獲取。

 

mutation
修改數據操做,你想對某項數據進行修改,就得守規矩。不能用 this.$store.state.count=99,要把修改函數寫在 mutation 裏面,用 this.commit('eventName') 觸發修改函數。注意,這裏的操做必須是同步。

 

action
異步觸發 mutation 。

 

module
給多個狀態模塊分類。

 

  轉自: https://www.jianshu.com/p/5624362cd1f4

相關文章
相關標籤/搜索