Vuex快速入門

文檔在這里: Vuex (vuejs.org)

1. Vuex 是什么?

Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測(cè)的方式發(fā)生變化。
狀態(tài)管理模式
讓我們從一個(gè)簡(jiǎn)單的 Vue 計(jì)數(shù)應(yīng)用開始:

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

這個(gè)狀態(tài)自管理應(yīng)用包含以下幾個(gè)部分:

  • state,驅(qū)動(dòng)應(yīng)用的數(shù)據(jù)源;
  • view,以聲明方式將 state 映射到視圖;
  • actions,響應(yīng)在 view 上的用戶輸入導(dǎo)致的狀態(tài)變化。

以下是一個(gè)表示“單向數(shù)據(jù)流”理念的簡(jiǎn)單示意:

image.png

然而當(dāng)多個(gè)組件共享狀態(tài)(也就是數(shù)據(jù))的時(shí)候,數(shù)據(jù)變動(dòng)的來源變得不明顯,邏輯變得繁瑣不清晰。那么 vuex 就是將組件的共享狀態(tài)抽取出來,以一個(gè)全局單例模式來管理的,專門為 Vue.js 設(shè)計(jì)的狀態(tài)管理庫(kù),它利用 Vue.js 的細(xì)粒度數(shù)據(jù)響應(yīng)機(jī)制來進(jìn)行高效的狀態(tài)更新。
vuex

通俗地來講,就是當(dāng)頁(yè)面應(yīng)用過多且復(fù)雜,這個(gè)時(shí)候就適合用 vuex 在組件外部管理狀態(tài)。

2. 安裝

直接下載

npm install vuex --save
// npm 或 yarn
yarn add vuex

// 在一個(gè)模塊化的打包系統(tǒng)中,必須顯式地通過 Vue.use() 來安裝 Vuex
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

CDN 引用
當(dāng)使用全局 script 標(biāo)簽引用 Vuex 時(shí),不需要以上安裝過程。

<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vuex"></script>

3. State

創(chuàng)建一個(gè) store,創(chuàng)建過程直截了當(dāng)——僅需要提供一個(gè)初始 state 對(duì)象和一些 mutation:

import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

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

現(xiàn)在,可以通過 store.state 來獲取狀態(tài)對(duì)象,以及通過 store.commit 方法觸發(fā)狀態(tài)變更:

store.commit('increment')
console.log(store.state.count) // -> 1

mapState函數(shù)
mapState 函數(shù)返回的是一個(gè)對(duì)象。它可以將多個(gè)對(duì)象合并為一個(gè),以使我們可以將最終對(duì)象傳給 computed 屬性。

image.png

其中 ... 叫做 對(duì)象擴(kuò)展運(yùn)算符,可以將 mapState 返回的對(duì)象展開在所在位置上。

4. Getters

Vuex 允許我們?cè)?store 中定義“getter”(可以認(rèn)為是 store 的計(jì)算屬性)。就像計(jì)算屬性一樣,getter 的返回值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算。
Getter 接受 state 作為其第一個(gè)參數(shù),如果需要的話也可以接受其他 getter 作為第二個(gè)參數(shù)。

image.png

實(shí)例中的 fullName() 函數(shù)可以換成 ...Vuex.mapGetters(['fullName'])

5. Mutation

更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方。
在上面的兩個(gè)例子之中已經(jīng)使用到了 mutation 。
還可以向 mutation 傳入額外的參數(shù),當(dāng)然也可以傳遞一個(gè)對(duì)象。

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

Mutation 需遵守 Vue 的響應(yīng)規(guī)則

  1. 需要提前在 store 中初始化好所有所需屬性。
  2. 當(dāng)需要在對(duì)象上添加新屬性時(shí),你應(yīng)該
  • 使用 Vue.set(obj, 'newProp', 123), 或者
  • 以新對(duì)象替換老對(duì)象。

Mutation 必須是同步函數(shù)
每一條 mutation 都會(huì)被記錄,如果使用異步,在 devtools 上將會(huì)很難捕捉前一狀態(tài)與后一狀態(tài)的快照。(實(shí)質(zhì)上任何在回調(diào)函數(shù)中進(jìn)行的狀態(tài)的改變都是不可追蹤的)
在組件中提交 Mutation
可以在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 輔助函數(shù)將組件中的 methods 映射為 store.commit 調(diào)用(需要在根節(jié)點(diǎn)注入 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')`
    })
  }
}

6. Action

Action 類似于 mutation,不同在于:

  • Action 提交的是 mutation,而不是直接變更狀態(tài)。
  • Action 可以包含任意異步操作。
    讓我們來注冊(cè)一個(gè)簡(jiǎn)單的 action:
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
      context.commit('increment')
    }
  }
})

Action 函數(shù)接受一個(gè)與 store 實(shí)例具有相同方法和屬性的 context 對(duì)象,因此你可以調(diào)用 context.commit 提交一個(gè) mutation,或者通過 context.statecontext.getters 來獲取 state 和 getters。
使用es6可以簡(jiǎn)化代碼為:

actions: {
  increment ({ commit }) {
    commit('increment')
  }
}

分發(fā)Action
Action 通過 store.dispatch 方法觸發(fā):

store.dispatch('increment')

我們可以在 action 內(nèi)部執(zhí)行異步操作,也支持同樣的載荷方式和對(duì)象方式進(jìn)行分發(fā):

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

// 以載荷形式分發(fā)
store.dispatch('incrementAsync', {
  amount: 10
})

// 以對(duì)象形式分發(fā)
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})

來看一個(gè)更加實(shí)際的購(gòu)物車示例,涉及到調(diào)用異步 API 和分發(fā)多重 mutation:

actions: {
  checkout ({ commit, state }, products) {
    // 把當(dāng)前購(gòu)物車的物品備份起來
    const savedCartItems = [...state.cart.added]
    // 發(fā)出結(jié)賬請(qǐng)求,然后樂觀地清空購(gòu)物車
    commit(types.CHECKOUT_REQUEST)
    // 購(gòu)物 API 接受一個(gè)成功回調(diào)和一個(gè)失敗回調(diào)
    shop.buyProducts(
      products,
      // 成功操作
      () => commit(types.CHECKOUT_SUCCESS),
      // 失敗操作
      () => commit(types.CHECKOUT_FAILURE, savedCartItems)
    )
  }
}

簡(jiǎn)單地來說,就相當(dāng)于我讓朋友幫我去買書,買成功了就跟這個(gè)管理員結(jié)賬,如果不成功,就去找另一個(gè)來解決。那么這個(gè) checkout 就相當(dāng)于朋友。

7. Modules

Vuex 允許我們將 store 分割成模塊(module)。每個(gè)模塊擁有自己的 state、mutation、action、getter、甚至是嵌套子模塊——從上至下進(jìn)行同樣方式的分割:

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 的狀態(tài)
store.state.b // -> moduleB 的狀態(tài)
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1.vuex是什么 Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有...
    芒果香蕉蘋果梨閱讀 178評(píng)論 0 0
  • 本文為課程 vuex深入淺出 的學(xué)習(xí)總結(jié)與記錄;同時(shí)參照了vuex官方文檔。文中demo的代碼可參考:我的碼云 一...
    明滅_閱讀 8,821評(píng)論 1 28
  • Vuex是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的...
    夢(mèng)安web開發(fā)閱讀 294評(píng)論 0 2
  • Vuex的概述 Vuex是什么 Vuex是實(shí)現(xiàn)組件全局狀態(tài)(數(shù)據(jù))管理的一種機(jī)制,可以方便的實(shí)現(xiàn)組件之間數(shù)據(jù)的共享...
    Tammie_a56e閱讀 398評(píng)論 0 1
  • 一、Vuex是什么 Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存儲(chǔ)管理應(yīng)用的所有...
    尋找夢(mèng)的豬豬閱讀 428評(píng)論 0 0

友情鏈接更多精彩內(nèi)容