玩爛 Vuex

Vuex 概念篇

Vuex 是什么魔策?

Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式姜钳。它采用集中式存儲管理應(yīng)用的所有組件的狀態(tài),并以相應(yīng)的規(guī)則保證狀態(tài)以一種可預(yù)測的方式發(fā)生變化遇八。

什么是“狀態(tài)管理模式”?

從軟件設(shè)計的角度丽啡,就是以一種統(tǒng)一的約定和準(zhǔn)則,對全局共享狀態(tài)數(shù)據(jù)進行管理和操作的設(shè)計理念硬猫。你必須按照這種設(shè)計理念和架構(gòu)來對你項目里共享狀態(tài)數(shù)據(jù)進行CRUD补箍。所以所謂的“狀態(tài)管理模式”就是一種軟件設(shè)計的一種架構(gòu)模式(思想)改执。

為什么需要這種“狀態(tài)管理模式”應(yīng)用到項目中呢?

現(xiàn)如今坑雅,流行組件化辈挂、模塊化開發(fā),多人開發(fā)各自組件的時候裹粤,不難保證各個組件都是唯一性的终蒂,多個組件共享狀態(tài)肯定是存在的,共享狀態(tài)又是誰都可以進行操作和修改的遥诉,這樣就會導(dǎo)致所有對共享狀態(tài)的操作都是不可預(yù)料的拇泣,后期出現(xiàn)問題,進行 debug 也是困難重重矮锈,往往我們是盡量去避免全局變量霉翔。

但大量的業(yè)務(wù)場景下,不同的模塊(組件)之間確實需要共享數(shù)據(jù)苞笨,也需要對其進行修改操作债朵。也就引發(fā)軟件設(shè)計中的矛盾:模塊(組件)之間需要共享數(shù)據(jù)數(shù)據(jù)可能被任意修改導(dǎo)致不可預(yù)料的結(jié)果

為了解決其矛盾瀑凝,軟件設(shè)計上就提出了一種設(shè)計和架構(gòu)思想序芦,將全局狀態(tài)進行統(tǒng)一的管理,并且需要獲取猜丹、修改等操作必須按我設(shè)計的套路來。就好比馬路上必須遵守的交通規(guī)則硅卢,右行斑馬線就是只能右轉(zhuǎn)一個道理射窒,統(tǒng)一了對全局狀態(tài)管理的唯一入口,使代碼結(jié)構(gòu)清晰将塑、更利于維護脉顿。

Vuex 是借鑒了 Flux 、Redux 和 The Elm Architecture 架構(gòu)模式点寥、設(shè)計思想的產(chǎn)物艾疟。

Vuex運行機制

什么情況下我應(yīng)該使用 Vuex?

不打算開發(fā)大型單頁應(yīng)用敢辩,使用 Vuex 可能是繁瑣冗余的蔽莱。應(yīng)用夠簡單,最好不要使用 Vuex戚长。一個簡單的 global event bus (父子組件通信盗冷,父組件管理所需的數(shù)據(jù)狀態(tài))就足夠您所需了。構(gòu)建一個中大型單頁應(yīng)用同廉,您很可能會考慮如何更好地在組件外部管理狀態(tài)仪糖,Vuex 將會成為自然而然的選擇柑司。

個人見解,什么時候用锅劝?管你小中大型應(yīng)用攒驰,我就想用就用唄,一個長期構(gòu)建的小型應(yīng)用項目故爵,誰能知道項目需求以后會是什么樣子玻粪,畢竟在這浮躁的時代,需求就跟川劇變臉一樣快稠集,對不對奶段?畢竟學(xué)習(xí)了 Vuex 不立馬用到項目實戰(zhàn)中,你永遠不可能揭開 Vuex 的面紗剥纷。項目中使用多了痹籍,自然而然就會知道什么時候該用上狀態(tài)管理,什么時候不需要晦鞋。老話說的好熟能生巧蹲缠,你認為呢?
(括弧 -- 先了解好Vuex 一些基本概念悠垛,然后在自己的項目中使用過后线定,再用到你公司項目上,你別這么虎一上來就給用上去了~)

Vuex 基本使用篇

安裝

npm i vuex -S

項目全局中任何地方使用 Vuex, 需要將 Vuex 注冊到 Vue 實例中:

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

Vue.use(Vuex)

Vuex 上車前的一個??

上車規(guī)則:

  1. 每一個 Vuex 應(yīng)用的核心就是 store(倉庫)确买,一個項目中必須只有一個 store 實例斤讥。包含著你的應(yīng)用中大部分的狀態(tài) (state)。
  2. 不能直接改變 store 中的狀態(tài)湾趾。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation芭商。

Vuex 和單純的全局對象有以下兩點不同:
(1) Vuex 的狀態(tài)存儲是響應(yīng)式的。Vue 組件從 store 中讀取狀態(tài)的時候搀缠,若 store 中的狀態(tài)發(fā)生變化铛楣,那么相應(yīng)的組件也會相應(yīng)地得到高效更新。
(2)不能直接改變 store 中的狀態(tài)艺普。(重要的事情多來一遍)

上??:

<div id="app">
  <p>{{ count }}</p>
  <p>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </p>
</div>

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

Vue.use(Vuex) // Vuex 注冊到 Vue 中

// 創(chuàng)建一個 store

const store = new Vuex.Store({
  // 初始化 state   
  state: {
    count: 0
  },
 // 改變狀態(tài)唯一聲明處
  mutations: {
    increment: state => state.count++,
    decrement: state => state.count--
  }
})

new Vue({
  el: '#app',
  // 從根組件將 store 的實例注入到所有的子組件  
  store,  
  computed: {
    count () {
        // Vuex 的狀態(tài)存儲是響應(yīng)式的簸州,從 store 實例中讀取狀態(tài)最簡單的方法就是在計算屬性中返回某個狀態(tài),
        // 每當(dāng)狀態(tài) count 發(fā)生變化,都會重新求取計算
        return this.$store.state.count
    }
  },
  methods: {
    increment () {
      this.$store.commit('increment')
    },
    decrement () {
        this.$store.commit('decrement')
    }
  }
})

state 一個對象管理應(yīng)用的所有狀態(tài)歧譬,唯一數(shù)據(jù)源(SSOT, Single source of truth)岸浑,必須前期初始化就定義好,不然后面在來修改設(shè)置 state瑰步,程序就不會捕獲到 mutations(突變的意思) 所以數(shù)據(jù)也就不會又任何的更新助琐,組件上也無法體現(xiàn)出來。

獲取 store 管理的狀態(tài)面氓, 因為在 Vue 實例化的時候?qū)?Vuex store 對象 注入了進來 兵钮,所以任何地方都可以通過 this.$store 獲取到 store, this.$store.state 來獲取狀態(tài)對象蛆橡, this.$store.commit 來觸發(fā)之前定義好的 mutations 中的方法

this.$store.state('count') // => 0

this.$store.commit('increment') // => 1

通過提交 mutation 的方式,而非直接改變 store.state.count, 使用 commit 方式可以讓 Vuex 明確地追蹤到狀態(tài)的變化掘譬,利于后期維護和調(diào)試泰演。

通過了解 state (狀態(tài),數(shù)據(jù))和 mutations (修改數(shù)據(jù)唯一聲明的地方葱轩,類似 SQL 語句)知道了 Vuex 最重要的核心兩部分睦焕,然后通過掌握 gttter、action靴拱、module 來讓 Vuex 更加的工程化垃喊、合理化來適應(yīng)更大型的項目的狀態(tài)管理。

mapState 輔助函數(shù)

mapState 可以干什么呢袜炕?字面意思狀態(tài)映射本谜,通過 mapState 可以更加快捷方便幫我們生成計算屬性,拿上面的例子進行演示:

 computed: {
    count () {
        return this.$store.state.count
    }
 }

// 使用 mapState

import { mapState } from 'vuex' // 需要先導(dǎo)入

computed: mapState([
    // 箭頭函數(shù)方式
    count: state => state.count ,
    
    // or 傳字符串參數(shù)方式, 'count' 等同于 state => state.count
    countAlias: 'count'
    
    // 獲取狀態(tài)后偎窘,你還需要和當(dāng)前組件別的屬性值時,就必須使用常規(guī)函數(shù)的寫法了, 只有這樣才能獲取到當(dāng)前組件的 this
    countPlusLocalState (state) {
        return state.count + this.localCount
    } 
])

當(dāng)前計算屬性名稱和狀態(tài)名稱相同時乌助,可以傳遞一個字符串?dāng)?shù)組:

computed: mapState([
    // 映射 `this.count` 為 `this.$store.state.count`
    'count'
])

以上使用 mapState 輔助函數(shù)后,整個 computed 計算屬性都成了 state 狀態(tài)管理聚集地了陌知, 組件里并不是所有的計算屬性都需要被狀態(tài)管理化他托,還是有很多計算屬性是不需要狀態(tài)管理的數(shù)據(jù)的,那如何將它與局部計算屬性混合使用呢仆葡?

因為 mapState 函數(shù)返回的是一個對象赏参。所以我們使用對象擴展運算符就可以把局部計算屬性和 mapState 函數(shù)返回的對象融合了。

computed: {
    ...mapState({
        count: state => state.count    
    }),
    
   localComputed () {
       /* ... */ 
   }     
}

?? 注意:
對象擴展運算符沿盅,現(xiàn)處于 ECMASCript 提案 stage-4 階段(將被添加到下一年度發(fā)布)把篓,所以項目中要使用需要安裝 babel-plugin-transform-object-rest-spread 插件 或 安裝 presets 環(huán)境為 stage 為 1的 env 版本 babel-preset-stage-1 和修改 babelrc 配置文件

.babelrc

{
    "presets": [
        "env",
        "stage-1" // 添加此項
    ],
    "plugins": [
        "transform-vue-jsx",
        "syntax-dynamic-import"
    ]
}

核心概念

上面以講述過 state 了,這里就不過多的說明嗡呼。

Getter

Getter 就是 Store 狀態(tài)管理層中的計算屬性纸俭,獲取源 State 后皇耗,希望在對其進行一些包裝南窗,再返回給組件中使用。也是就將直接獲取到 State 后在 computed 里進行再次的過濾郎楼、包裝邏輯統(tǒng)統(tǒng)提取出放到 Getter 里進行万伤,提高了代碼的復(fù)用性、可讀性呜袁。

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

提取到 Getter


const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  //  `Getter` 默認第一個參數(shù)為 `state`:  
  getters: {
    doneTodos: state => {
      return state.todos.filter( todo => todo.done )
    }
  }
})


//  組件中獲取敌买,通過屬性訪問

computed: {
    doneTodosCount () {
        return this.$store.getters.doneTodos.length
    } 
}

?? 注意: getter 在通過屬性訪問時是作為 Vue 的響應(yīng)式系統(tǒng)的一部分進行緩存。

Getter 還接受其他 getter 作為第二個參數(shù)


const store = new Vuex.Store({
  state: {
    todos: [
      { id: 1, text: '...', done: true },
      { id: 2, text: '...', done: false }
    ]
  },
  getters: {
    doneTodos: state => {
      return state.todos.filter( todo => todo.done )
    },
    // 第二個參數(shù)為 getters  
    doneTodosLength: (state, getters) => {
        return getters.doneTodos.length
    }  
  }
})

還可以通過給 Getter 傳遞參數(shù)獲取特定的數(shù)據(jù)


getters: {
    // ...
    
    getTodoById: state => id => {
        return state.todos.find( todo => todo.id === id )
    }
}

組件內(nèi)調(diào)用方式


this.$store.getters.getTodoById(2) // => { id: 2, text: '...', done: false }

?? 注意:getter 在通過方法訪問時阶界,每次都會去進行調(diào)用虹钮,而不會緩存結(jié)果聋庵。

mapGetters 輔助函數(shù)

和前面 mapState 輔助函數(shù)作用和使用上基本相同。


import { mapGetters } from 'vuex'

// getter 名稱和 計算屬性名稱相同的情況下芙粱,可以傳遞字符串?dāng)?shù)組

export default {
  // ...
  computed: {
    ...mapGetters([
        'doneTodos'
    ])
  }
}

// 傳遞對象的方式

export default {
  // ...
  computed: {
    ...mapGetters({
        doneTodos: 'doneTodos',
        getTodoById: 'getTodoById' // 此處傳遞回來的是一個函數(shù)祭玉,所以在使用的時候 => {{ getTodoById(2) }}
    })
  }
}

Mutation

不能直接修改狀態(tài),需要通過 Vuex store 中聲明的 Mutations 里的方法修改狀態(tài)春畔。 更改 Vuex 的 store 中的狀態(tài)的唯一方法是提交 mutation脱货。mutation 是一個對象, 含有一個字符串的 事件類型 (type) 和 一個 回調(diào)函數(shù) (handler)律姨。
回調(diào)函數(shù)就是我們實際進行狀態(tài)更改的地方振峻,默認接受 state 作為第一個參數(shù)。

const store = new Vuex.Store({
  state: {
    count: 1
  },
  mutations: {
    // increment 事件類型(type)名稱择份,increment() 回調(diào)函數(shù)
    // increment: function (state) {}  原本寫法
    increment (state) {
      // 變更狀態(tài)
      state.count++
    }
  }
})

mutation handler 不能被直接調(diào)用扣孟,需要通過 store.commit() 來通知我需要觸發(fā)一個 mutation handler

this.$store.commit('increment')

mutation 接收參數(shù)必須只能兩個缓淹,超出的都無法獲裙颉;第二個參數(shù)推薦傳遞的是一個對象讯壶,來接收更多的信息料仗。

this.$store.commit('increment', 10) 

// or

this.$store.commit('increment', { num: 10 }) 

對象風(fēng)格的提交方式

this.$store.commit({
    type: 'increment',
    num: 10
})

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

Vuex 的 store 中的狀態(tài)是響應(yīng)式的,那么當(dāng)我們變更狀態(tài)時伏蚊,監(jiān)視狀態(tài)的 Vue 組件也會自動更新立轧。這也意味著 Vuex 中的 mutation 也需要與使用 Vue 一樣遵守一些注意事項:

  1. 最好提前在你的 store 中初始化好所有所需屬性(state 中的屬性)。
  2. 當(dāng)需要在對象上添加新屬性時躏吊,你應(yīng)該返回的是一個新對象
    * 使用 Vue.set(obj, 'newProp', 123)氛改,或者
    * 以新對象替換老對象。例如: Object.assgin({}, state.obj, newProps) 比伏、對象擴展運算符 state.obj = {...state.obj, newProp: 123 }

mapMutation 輔助函數(shù)

使用方式跟 mapStatemapGetters 基本相同胜卤。

import { mapMutations } from 'vuex'

export default {
  // ...
  methods: {
    // 傳遞字符串?dāng)?shù)組,同名哦~  
    ...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')`
    })
  }
}

調(diào)用方式就跟 methods 其他普通方法一樣赁项,通過 this.<methodName> 來調(diào)用葛躏。

?? 注意:
mutation 必須是同步函數(shù),修改 state 必須是同步的悠菜、同步的舰攒、同步的。
如果是異步的悔醋,當(dāng)觸發(fā) mutation 的時候摩窃,內(nèi)部的回調(diào)函數(shù)還沒有被調(diào)用,根本不知道實際執(zhí)行在何處芬骄,很難追蹤起問題猾愿。(實質(zhì)上任何在回調(diào)函數(shù)中進行的狀態(tài)的改變都是不可追蹤的鹦聪。
Vuex 也提供了異步操作的解決方案, 需要將異步操作提取出來放入到 Action 里進行操作蒂秘。而 Mutation 只負責(zé)同步事務(wù)椎麦。

Action

在之前也講述了,Action 是用來處理異步操作的材彪。這里在詳細說明一下 Action 的基本使用观挎。

Action 類似于 mutation, 不同在于:

  • Action 提交的是 mutation段化,而不是直接變更狀態(tài)嘁捷。(不直接修改狀態(tài),修改狀態(tài)還是需要通過 mutation)
  • Action 可以包含任意異步操作显熏。
const store = new Vuex.Store({
  state: {
    count: 0
  },
  mutations: {
    increment (state) {
      state.count++
    }
  },
  actions: {
     // 實踐中雄嚣,經(jīng)常用到參數(shù)解構(gòu)來簡化代碼, increment ({commit}) { commit('') }
    increment (context) {
      context.commit('increment')
    }
  }
})

Action 函數(shù)接受一個與 store 實例具有相同方法和屬性的 context 對象(并不是真正的 store 本身)喘蟆,因此可以調(diào)用 store.commit 進行提交 mutation缓升, 或者通過 context.statecontext.getters 來獲取 stategetters

觸發(fā)Action

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

this.$store.dispatch('increment')

// 以傳遞額外參數(shù)分發(fā)
store.dispatch('incrementAsync', {
  amount: 10
})

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

與服務(wù)器數(shù)據(jù)異步請求基本在 Action 里進行蕴轨, 然后通過 Mutation 來同步應(yīng)用狀態(tài)state

mapAction 輔助函數(shù)

mapMutions 使用方式基本一致港谊。

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')`
    })
  }
}

組合 Action

Action 通常是異步的,那么如何知道 action 什么時候結(jié)束呢橙弱?更重要的是歧寺,我們?nèi)绾尾拍芙M合多個 action,以處理更加復(fù)雜的異步流程棘脐?

通過返回一個 Promise 對象來進行組合多個 Action斜筐。


actions: {
  actionA ({ commit }) {
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        commit('someMutation')
        resolve()
      }, 1000)
    })
  }
}

然后:

store.dispatch('actionA').then(() => {
  // ...
})

利用 async / await,我們可以如下組合 action:


// 假設(shè) getData() 和 getOtherData() 返回的是 Promise

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

Module

由于 Vuex 使用單一狀態(tài)樹模式蛀缝,來統(tǒng)一管理應(yīng)用所有的狀態(tài)顷链,導(dǎo)致所有狀態(tài)會集中到一個比較大的對象,隨著后續(xù)不斷得迭代屈梁,這個對象就會越來越龐大嗤练,后期的代碼可讀性、可維護性就會不斷加大俘闯。

解決以上問題潭苞,就需要對這個對象的內(nèi)部進行拆分和細分化忽冻,對狀態(tài)進行分門別類真朗,也就產(chǎn)生了模塊(module) 這個概念。每個模塊擁有自己的 state僧诚、mutation遮婶、action蝗碎、getter、甚至是嵌套子模塊——從上至下進行同樣方式的分割旗扑,將龐大的系統(tǒng)進行合理有效的職能劃分蹦骑,遵循單一職責(zé)的理念,每個模塊清晰明了的自己的職責(zé)和職能臀防。

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)

聲明模塊后眠菇,state、mutation袱衷、action捎废、getter 等使用方式、作用和不在 modules 內(nèi)聲明方式基本一樣致燥,只是在細節(jié)上進行了一些細微的改變登疗,比如: getter 里默認接收一個參數(shù) state,模塊里接收 state 就是本身模塊自己的 state 狀態(tài)了嫌蚤,而不是全局的了辐益; 調(diào)用獲取上也多一道需要告知那個模塊獲取狀態(tài) 等一些細節(jié)上的差異。

Module 里 state脱吱、mutation智政、action、getter 上的一些差異

(1)模塊內(nèi)部的 mutation 和 getter箱蝠,接收的第一個參數(shù) state模塊的局部狀態(tài)對象女仰。
(2)模塊內(nèi)部的 action,局部狀態(tài)通過 context.state 暴露出來抡锈,根節(jié)點狀態(tài)則為 context.rootState
(3)模塊內(nèi)部的 getter疾忍,根節(jié)點狀態(tài)會作為第三個參數(shù)暴露出來

命名空間

默認情況下峰档,模塊內(nèi)部的 action底循、mutation 和 getter 是注冊在全局命名空間的——這樣使得多個模塊能夠?qū)ν?mutation 或 action 作出響應(yīng),所以必須防止模塊里屬性或方法重名灯蝴。

為了模塊具有更高的封裝度撇簿、復(fù)用性和獨立性聂渊,可以通過添加 namespaced: true 的方式使其成為帶命名空間的模塊。在調(diào)用上也就需要添加上聲明 getter四瘫、action 及 mutation 到底屬于那個模塊了汉嗽,以路徑的形式表示屬于那個模塊。


const store = new Vuex.Store({
  modules: {
    account: {
      namespaced: true, // 開啟命名空間

      // 模塊內(nèi)容(module assets)
      state: { ... }, // 模塊內(nèi)的狀態(tài)已經(jīng)是嵌套的了找蜜,使用 `namespaced` 屬性不會對其產(chǎn)生影響
      getters: {
        isAdmin () { ... } // -> getters['account/isAdmin'] 調(diào)用時以路徑的形式表明歸屬
      },
      actions: {
        login () { ... } // -> dispatch('account/login')
      },
      mutations: {
        login () { ... } // -> commit('account/login')
      },

      // 嵌套模塊
      modules: {
        // 繼承父模塊的命名空間
        myPage: {
          state: { ... },
          getters: {
            profile () { ... } // -> getters['account/profile']
          }
        },

        // 進一步嵌套命名空間
        posts: {
          namespaced: true,

          state: { ... },
          getters: {
            popular () { ... } // -> getters['account/posts/popular']
          }
        }
      }
    }
  }
})

在帶命名空間的模塊內(nèi)訪問全局內(nèi)容

帶命名空間的模塊內(nèi)訪問全局 state 饼暑、getter 和 action, rootStaterootGetter會作為第三和第四參數(shù)傳入 getter,也會通過 context 對象的屬性傳入 action弓叛。

需要在全局命名空間內(nèi)分發(fā) action 或提交 mutation彰居,將 { root: true } 作為第三參數(shù)傳給 dispatchcommit 即可。


modules: {
  foo: {
    namespaced: true,

    getters: {
      // 在這個模塊的 getter 中撰筷,`getters` 被局部化了
      // 全局的 state 和 getters 可以作為第三陈惰、四個參數(shù)進行傳入毕籽,從而訪問全局 state 和 getters
      someGetter (state, getters, rootState, rootGetters) {
        getters.someOtherGetter // -> 'foo/someOtherGetter'
        rootGetters.someOtherGetter // -> 'someOtherGetter'
      },
      someOtherGetter: state => { ... }
    },

    actions: {
      // 在這個模塊中, dispatch 和 commit 也被局部化了
      // 他們可以接受 `root` 屬性以訪問根 dispatch 或 commit
      someAction ({ dispatch, commit, getters, rootGetters }) {
        getters.someGetter // -> 'foo/someGetter'
        rootGetters.someGetter // -> 'someGetter'

        dispatch('someOtherAction') // -> 'foo/someOtherAction'
        dispatch('someOtherAction', null, { root: true }) // -> 'someOtherAction'

        commit('someMutation') // -> 'foo/someMutation'
        commit('someMutation', null, { root: true }) // -> 'someMutation'
      },
      someOtherAction (ctx, payload) { ... }
    }
  }
}

在帶命名空間的模塊注冊全局 action

需要在帶命名空間的模塊注冊全局 action画髓,你可添加 root: true,并將這個 action 的定義放在函數(shù) handler 中平委。例如:

{
  actions: {
    someOtherAction ({dispatch}) {
      dispatch('someAction')
    }
  },
  modules: {
    foo: {
      namespaced: true,

      actions: {
        someAction: {
          root: true,
          handler (namespacedContext, payload) { ... } // -> 'someAction'
        }
      }
    }
  }
}
帶命名空間的模塊里輔助函數(shù)如何使用奈虾?

將模塊的空間名稱字符串作為第一個參數(shù)傳遞給上述函數(shù)廉赔,這樣所有綁定都會自動將該模塊作為上下文。

computed: {
  ...mapState('some/nested/module', {
    a: state => state.a,
    b: state => state.b
  })
},
methods: {
  ...mapActions('some/nested/module', [
    'foo',
    'bar'
  ])
}

還可以通過使用 createNamespacedHelpers 創(chuàng)建基于某個命名空間輔助函數(shù)蜡塌。它返回一個對象碉纳,對象里有新的綁定在給定命名空間值上的組件綁定輔助函數(shù):

import { createNamespacedHelpers } from 'vuex'

const { mapState, mapActions } = createNamespacedHelpers('some/nested/module')

export default {
  computed: {
    // 在 `some/nested/module` 中查找
    ...mapState({
      a: state => state.a,
      b: state => state.b
    })
  },
  methods: {
    // 在 `some/nested/module` 中查找
    ...mapActions([
      'foo',
      'bar'
    ])
  }
}

模塊動態(tài)注冊

在 store 創(chuàng)建之后,你可以使用 store.registerModule 方法注冊模塊:

// 注冊模塊 `myModule`
store.registerModule('myModule', {
  // ...
})
// 注冊嵌套模塊 `nested/myModule`
store.registerModule(['nested', 'myModule'], {
  // ...
})

模塊動態(tài)注冊功能使得其他 Vue 插件可以通過在 store 中附加新模塊的方式來使用 Vuex 管理狀態(tài)劳曹。例如琅摩,vuex-router-sync 插件就是通過動態(tài)注冊模塊將 vue-routervuex 結(jié)合在一起,實現(xiàn)應(yīng)用的路由狀態(tài)管理蜕劝。

你也可以使用 store.unregisterModule(moduleName)來動態(tài)卸載模塊轰异。注意岖沛,你不能使用此方法卸載靜態(tài)模塊(即創(chuàng)建 store 時聲明的模塊)婴削。

待更新~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末牙肝,一起剝皮案震驚了整個濱河市嗤朴,隨后出現(xiàn)的幾起案子互躬,更是在濱河造成了極大的恐慌颂郎,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件寺酪,死亡現(xiàn)場離奇詭異替劈,居然都是意外死亡,警方通過查閱死者的電腦和手機盒犹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門眨业,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卓嫂,你說我怎么就攤上這事聘殖。” “怎么了奸腺?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵突照,是天一觀的道長。 經(jīng)常有香客問我绷旗,道長,這世上最難降的妖魔是什么庄岖? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任角骤,我火速辦了婚禮心剥,結(jié)果婚禮上背桐,老公的妹妹穿的比我還像新娘。我一直安慰自己畦娄,他們只是感情好弊仪,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著驳癌,像睡著了一般役听。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上典予,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天熙参,我揣著相機與錄音,去河邊找鬼昭娩。 笑死黍匾,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的锐涯。 我是一名探鬼主播,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼升薯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起广凸,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎脸哀,沒想到半個月后扭吁,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡谅摄,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了顽照。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡代兵,死狀恐怖植影,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情思币,我是刑警寧澤,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布惶我,位于F島的核電站博投,受9級特大地震影響毅哗,放射性物質(zhì)發(fā)生泄漏虑绵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一筷厘、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧酥艳,春花似錦、人聲如沸莫换。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至撕瞧,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間巩掺,已是汗流浹背页畦。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留独令,地道東北人州胳。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓栓撞,卻偏偏與公主長得像,于是被迫代替她去往敵國和親瓤湘。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容

  • Vuex 是什么? ** 官方解釋:Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式**木人。它采用集中...
    Rz______閱讀 2,296評論 1 10
  • 學(xué)習(xí)目的 了解和熟練使用 VueX,能夠在實際項目中運用渔嚷。 VueX介紹 Vuex 是一個專為 Vue.js ...
    _1633_閱讀 2,785評論 0 7
  • 前言 用過vue的同學(xué)應(yīng)該都知道在vue里有個狀態(tài)管理器形病,其實一開始我對vuex還不是很理解,甚至還不知道怎么用漠吻,...
    慕小牧閱讀 1,382評論 0 3
  • vuex學(xué)習(xí)筆記 vuex是什么途乃? Vuex 是一個專為 Vue.js 應(yīng)用程序開發(fā)的狀態(tài)管理模式。它采用集中式存...
    EL_PSY_CONGROO閱讀 766評論 0 0
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,520評論 25 707