Vuex的使用及原理

1、Vuex 是什麼?

在理解Vuex的使用和原理以前首先要知道Vuex是什麼?按照官方的說法,Vuex是專門爲Vuejs應用程序設計的一款狀態管理模式,相似於React中的Redux。它採用集中式存儲管理應用的全部組件的狀態。前端

一、 Vuex的構成

下面圖片很清晰的展現出了Vuex的組成結構vue

  • state

state 是 Vuex 的數據中心,也就是說state是用來存儲數據的。vuex

  • Getters

getters 和 組件的 computed 相似,方便直接生成一些能夠直接用的數據。當組裝的數據要在多個頁面使用時,就可使用 getters 來作。npm

  • Mutations

mutations提交更改數據,使用store.commit方法更改state存儲的狀態。數組

  • Actions

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

二、Vuex的使用方式

  • 安裝Vuex

    方式一: npm 方式
    npm install vuex --save
    複製代碼
    方式二: yarn 方式
    yarn add vuex
    複製代碼
  • 在應用中引入Vuex

import Vue from 'vue'
    import Vuex from 'vuex'
    Vue.use(Vuex)   
複製代碼
  • 在 Vue 組件中得到 Vuex 狀態(State)

    方式一: this.$store.state獲取bash

    經過在根實例中註冊 store 選項,該 store 實例會注入到根組件下的全部子組件中,且子組件能經過 this.$store 訪問到異步

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

    方式二: mapState 輔助函數獲取(推薦)函數

    當一個組件須要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。爲了解決這個問題,咱們可使用 mapState 輔助函數幫助咱們生成計算屬性,讓你少按幾回鍵:ui

    import { mapState } from "vuex";
        export default {
        // ...
        computed: mapState({
            // 箭頭函數可以使代碼更簡練
            count: state => state.count,
    
            // 傳字符串參數 'count' 等同於 `state => state.count`
            countAlias: 'count',
    
            // 爲了可以使用 `this` 獲取局部狀態,必須使用常規函數
            countPlusLocalState (state) {
                return state.count + this.localCount
            }
        })
    }
    複製代碼

    當映射的計算屬性的名稱與 state 的子節點名稱相同時,咱們也能夠給 mapState 傳一個字符串數組。

    computed: mapState([
            // 映射 this.count 爲 store.state.count
            'count'
        ])
    複製代碼
  • Getter的獲取方式

    有時候咱們須要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數:

    computed: {
            doneTodosCount () {
                return this.$store.state.todos.filter(todo => todo.done).length
            } 
        }
    複製代碼

    若是有多個組件須要用到此屬性,咱們要麼複製這個函數,或者抽取到一個共享函數而後在多處導入它——不管哪一種方式都不是很理想。
    Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。

    方式一: 經過屬性訪問

    store.getters.doneTodos
    複製代碼

    方式二: 經過方法訪問

    你也能夠經過讓 getter 返回一個函數,來實現給 getter 傳參。在你對 store 裏的數組進行查詢時很是有用。

    getters: {
         // ...
         getTodoById: (state) => (id) => {
           return state.todos.find(todo => todo.id === id)
         }
       }
    複製代碼
    store.getters.getTodoById(2)
    複製代碼

    注意,getter 在經過方法訪問時,每次都會去進行調用,而不會緩存結果。

    方式三: mapGetters 輔助函數獲取(推薦)

    import { mapGetters } from 'vuex'
    
        export default {
          // ...
          computed: {
          // 使用對象展開運算符將 getter 混入 computed 對象中
            ...mapGetters([
              'doneTodosCount',
              'anotherGetter',
              // ...
            ])
          }
        }
    複製代碼

    若是你想將一個 getter 屬性另取一個名字,使用對象形式:

    mapGetters({
          // 把 `this.doneCount` 映射爲 `this.$store.getters.doneTodosCount`
          doneCount: 'doneTodosCount'
        })
    複製代碼
  • Mutation使用方式

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

    使用常量替代 Mutation 事件類型

    // mutation-types.js
        export const SOME_MUTATION = 'SOME_MUTATION'
    複製代碼
    // store.js
        import Vuex from 'vuex'
        import { SOME_MUTATION } from './mutation-types'
        
        const store = new Vuex.Store({
          state: { ... },
          mutations: {
            // 咱們可使用 ES2015 風格的計算屬性命名功能來使用一個常量做爲函數名
            [SOME_MUTATION] (state) {
              // mutate state
            }
          }
        })
    複製代碼

    固然使用常量代替Mutation事件類型也不是必須的,若是你不喜歡,你徹底能夠不這樣作。

    在組件中提交 Mutation

    你能夠在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 輔助函數將組件中的 methods 映射爲 store.commit 調用(須要在根節點注入 store)。

    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')`
            })
          }
        }
    複製代碼
  • Action使用方式

    Action的註冊

    Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters。當咱們在以後介紹到 Modules 時,你就知道 context 對象爲何不是 store 實例自己了。

    const store = new Vuex.Store({
          state: {
            count: 0
          },
          mutations: {
            increment (state) {
              state.count++
            }
          },
          actions: {
            increment (context) {
              context.commit('increment')
            }
          }
        })
    複製代碼

    分發 Action

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

    在組件中分發 Action

    你在組件中使用 this.$store.dispatch('xxx') 分發 action,或者使用 mapActions 輔助函數將組件的 methods 映射爲 store.dispatch 調用(須要先在根節點注入 store)

    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')`
            })
          }
        }
    複製代碼

    小結

    至此Vuex的使用及原理就介紹到這裏,若是還有不一樣理解的小夥伴們還請下發留言。若是有寫的很差的地方還請多多指教。我會繼續更新有關前端的技術文章的。

相關文章
相關標籤/搜索