vuex詳解

一、概念

Vuex是一個(gè)專為 Vue.js應(yīng)用程序開發(fā)的 狀態(tài)管理模式。
因?yàn)槟K間是不共享作用域的,平時(shí)用來解決共享參數(shù)的方法就是通過組件傳參,一旦項(xiàng)目變得很龐大,管理和維護(hù)這些值將是相當(dāng)棘手的事情。
這是我們就可以使用Vuex集中式存儲(chǔ)管理所有組件的狀態(tài)。

二、整體運(yùn)作流程

vuex.png

三、使用場景

如果您不打算開發(fā)大型單頁應(yīng)用,使用 Vuex 可能是繁瑣冗余的。確實(shí)是如此——如果您的應(yīng)用夠簡單,您最好不要使用 Vuex。一個(gè)簡單的 store 模式就足夠您所需了。但是,如果您需要構(gòu)建一個(gè)中大型單頁應(yīng)用,您很可能會(huì)考慮如何更好地在組件外部管理狀態(tài),Vuex 將會(huì)成為自然而然的選擇。

四、為啥不使用其他的狀態(tài)管理器,如redux

因?yàn)? Vuex是一個(gè)專門為 Vue應(yīng)用所設(shè)計(jì)。這使得它能夠更好地和Vue進(jìn)行整合,同時(shí)提供簡潔的 API 和改善過的開發(fā)體驗(yàn)。

五、五大核心

StateGetters、MutationsActions、Modules

mapStatemapGetters、mapMutations、mapActions

可以把 Vuex理解為 “前端的數(shù)據(jù)庫”。
state 就是數(shù)據(jù)庫。
getters 是用來從數(shù)據(jù)庫取數(shù)據(jù)的。既然是取,那么肯定是不能修改的,所以, getters 是一個(gè)“純函數(shù)”,即不會(huì)對元數(shù)據(jù)造成影響的函數(shù)。
mutations 是用來修改 state 的。只能是同步操作
actions可以理解成:我們從后端拿到數(shù)據(jù),總得做個(gè)處理。處理完了再存到數(shù)據(jù)庫中,當(dāng)然也可以不處理,就是直接mutation。包含異步操作。

State

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

// 創(chuàng)建一個(gè) Counter 組件
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return store.state.count
    }
  }
}
每當(dāng) store.state.count 變化的時(shí)候, 都會(huì)重新求取計(jì)算屬性,并且觸發(fā)更新相關(guān)聯(lián)的 DOM。

然而,這種模式導(dǎo)致組件依賴全局狀態(tài)單例。在模塊化的構(gòu)建系統(tǒng)中,在每個(gè)需要使用 state 的組件中需要頻繁地導(dǎo)入,并且在測試組件時(shí)需要模擬狀態(tài)。
Vuex 通過 store 選項(xiàng),提供了一種機(jī)制將狀態(tài)從根組件“注入”到每一個(gè)子組件中
(需調(diào)用 Vue.use(Vuex)):
const app = new Vue({
  el: '#app',
  // 把 store 對象提供給 “store” 選項(xiàng),這可以把 store 的實(shí)例注入所有的子組件
  store,
  components: { Counter },
  template: `
    <div class="app">
      <counter></counter>
    </div>
  `
})
通過在根實(shí)例中注冊 store 選項(xiàng),該 store 實(shí)例會(huì)注入到根組件下的所有子組件中,
且子組件能通過 this.$store 訪問到。讓我們更新下 Counter 的實(shí)現(xiàn):
const Counter = {
  template: `<div>{{ count }}</div>`,
  computed: {
    count () {
      return this.$store.state.count
    }
  }
}

mapState: 當(dāng)一個(gè)組件需要獲取多個(gè)狀態(tài)的時(shí)候,將這些狀態(tài)都聲明為計(jì)算屬性會(huì)有些重復(fù)和冗余。為了解決這個(gè)問題,我們可以使用 mapState 輔助函數(shù)幫助我們生成計(jì)算屬性。

// 在單獨(dú)構(gòu)建的版本中輔助函數(shù)為 Vuex.mapState
import { mapState } from 'vuex'
export default {
  // ...
  computed: mapState({
    // 箭頭函數(shù)可使代碼更簡練
    count: state => state.count,

    // 傳字符串參數(shù) 'count' 等同于 `state => state.count`
    countAlias: 'count',

    // 為了能夠使用 `this` 獲取局部狀態(tài),必須使用常規(guī)函數(shù)
    countPlusLocalState (state) {
      return state.count + this.localCount
    }
  })
}
mapState 函數(shù)返回的是一個(gè)對象。我們?nèi)绾螌⑺c局部計(jì)算屬性混合使用呢?通常,我們需要使用一個(gè)工具函數(shù)將多個(gè)對象合并為一個(gè),以使我們可以將最終對象傳給 computed 屬性。
computed: {
  localComputed () { /* ... */ },
  // 使用對象展開運(yùn)算符將此對象混入到外部對象中
  ...mapState({
    // ...
  })
}

Getter

當(dāng)組件多處要使用某屬性時(shí),我們可以使用getters(可以理解成store的計(jì)算屬性)得到。getter 的返回值會(huì)根據(jù)它的依賴被緩存起來,且只有當(dāng)它的依賴值發(fā)生了改變才會(huì)被重新計(jì)算。

// 通過屬性訪問
store.getters.doneTodos // -> [{ id: 1, text: '...' }]

getters: {
  // ...第一個(gè)參數(shù):state, 第二個(gè)參數(shù):其他getters
  doneTodosCount: (state, getters) => {
    return getters.doneTodos.length
  }
}
store.getters.doneTodosCount // -> 1

注意,getter 在通過屬性訪問時(shí)是作為 Vue 的響應(yīng)式系統(tǒng)的一部分緩存其中的。

// 通過方法訪問

注意,getter 在通過方法訪問時(shí),每次都會(huì)去進(jìn)行調(diào)用,而不會(huì)緩存結(jié)果。

mapGetters輔助函數(shù)僅僅是將 store 中的 getter 映射到局部計(jì)算屬性

import { mapGetters } from 'vuex'

export default {
  // ...
  computed: {
  // 使用對象展開運(yùn)算符將 getter 混入 computed 對象中
    ...mapGetters([
      doneCount: 'doneTodosCount', // 起別名
      'anotherGetter',
      // ...
    ])
  }
}

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)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù)。
”要喚醒一個(gè) mutation handler,你需要以相應(yīng)的 type 調(diào)用 store.commit 方法

// 倆種提交方法
store.commit('increment', {amount: 10})
store.commit({
  type: 'increment',
  amount: 10
})
mutations: {
  increment (state, payload) {
    state.count += payload.amount
  }
}

Action

Action 類似于 mutation,不同在于:

Action 提交的是 mutation,而不是直接變更狀態(tài)。
Action 可以包含任意異步操作。

const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
    increment (context) {
    // context 上下文對象,context.state, context.rootState
      context.commit('increment')
    }
  }
})
// 分發(fā)Action, 調(diào)用Action
store.dispatch('increment')

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

// 以對象形式分發(fā)
store.dispatch({
  type: 'incrementAsync',
  amount: 10
})
// 在組件中分發(fā) Action
this.$store.dispatch('xxx')

...mapActions([
      'increment', // 將 `this.increment()` 映射為 `this.$store.dispatch('increment')`

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

組合Action

  1. 處理異步操作,返回Promise
actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

store.dispatch('actionA').then(() => {
  // ...
})
  1. 利用async/await
// 假設(shè) getData() 和 getOtherData() 返回的是 Promise

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

一個(gè) store.dispatch 在不同模塊中可以觸發(fā)多個(gè) action 函數(shù)。在這種情況下,只有當(dāng)所有觸發(fā)函數(shù)完成后,返回的 Promise 才會(huì)執(zhí)行。

Module

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

state回事模塊的局部狀態(tài)對象。
對于模塊內(nèi)部的 action,局部狀態(tài)通過 context.state 暴露出來,根節(jié)點(diǎn)狀態(tài)則為 context.rootState。
getter、action都可以拿到第三個(gè)參數(shù)rootState

命名空間:namespaced: true

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

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

  • Vuex是做什么的? 官方解釋:Vuex 是一個(gè)專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用 集中式存儲(chǔ)...
    獨(dú)調(diào)1997閱讀 932評(píng)論 0 0
  • Vuex是做什么的? 官方解釋:Vuex是一個(gè)專為Vue.js應(yīng)用程序開發(fā)的狀態(tài)管理模式。 它采用集中式存儲(chǔ)管理應(yīng)...
    Flipped_kk閱讀 497評(píng)論 0 4
  • 為什么使用vuex 在中大型應(yīng)用中,應(yīng)用的各個(gè)組件間需要進(jìn)行數(shù)據(jù)傳遞,使用傳統(tǒng)方式繁瑣且不可控 Vuex 為所有組...
    _cxrs_閱讀 708評(píng)論 0 0
  • 在vue中我們通過vuex來管理狀態(tài),該值一但被修改,所有引用該值的地方都會(huì)自動(dòng)更新項(xiàng)目的src文件下的store...
    壓縮干糧閱讀 332評(píng)論 0 2
  • 一、什么是vuex ? 答: 通俗的來說,我們可以把全局需要用到的數(shù)據(jù)【例如: 數(shù)據(jù) a】放在vuex中,同理,v...
    嵐平果閱讀 259評(píng)論 0 0

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