初識vue 2.0(8):vuex進階
主要講三部分內容:
- vuex模塊化
- vuex命名空間
- mutations和actions
模塊化
由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象,當應用變得非常復雜時,store 對象就有可能變得相當臃腫。
為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module),每個模塊擁有自己的 state、mutation、action、getter。
因此,創建一個store目錄,用來存儲狀態。
store/
|_ index.js
|_ helloModule.js
|_ gameModule.js
在index.js中導出組件,並在main.js中註冊
/** * 狀態註冊 */ import helloState from ‘./helloModule.js‘ import gameState from ‘./gameModule.js‘ export const modules = { modules: { helloState, gameState } }
main.js
// ... import { modules } from ‘./store‘ Vue.use(Vuex) //集中狀態管理 const store = newVuex.Store(modules); new Vue({ el: ‘#app‘, store,//我在這兒 template: ‘<App/>‘, components: { App } })
命名空間
在命名空間出現之前,Module只是將狀態分開,mutations或actions卻沒有分開。在調用的時候,如果采用一樣的命名,在調用時就都會被執行。
因此大家一般將mutations或actions中的方法名抽象成常量,保存在單獨的文件中,以避免命名汙染。
有了命名空間之後,只要設置 namespaced: true,模塊間的方法便相互獨立,互不影響,在語法上,也會稍有修改。
helloModule.js
/* global module:true */ export default module = { // 開啟命名空間 namespaced: true, // 定義狀態 state: { msg: ‘我是Hello模塊‘ }, // 獲取狀態 getters: { msg: (state) => (txt) => { return txt + state.msg // 接受傳參 } }, // 改變狀態 mutations: { // 包含異步修改狀態 setMsg (state, msg) { state.msg = msg setTimeout(() => { state.msg = ‘mutations修改成功‘ // 使用commit直接調用此異步方法,能達到修改數據的目的,最終狀態沒辦法追蹤 }, 1000) }, // 不包含異步修改狀態 setMsg2 (state, msg) { state.msg = msg } }, actions: { // 異步修改狀態 setMsg (context, msg) { context.commit(‘setMsg2‘, msg) setTimeout(() => { context.commit(‘setMsg2‘, ‘actions修改成功‘) // 使用dispatch調用,此異步狀態修改可以追蹤 }, 1000) } } }
gameModule.js 略
mutations和actions
為什麽說mutation只能同步,而action通過commit,可以異步執行mutation?
官網解釋:
現在想象,我們正在 debug 一個 app 並且觀察 devtool 中的 mutation 日誌。每一條 mutation 被記錄,devtools 都需要捕捉到前一狀態和後一狀態的快照。然而,在上面的例子中 mutation 中的異步函數中的回調讓這不可能完成:因為當 mutation 觸發的時候,回調函數還沒有被調用,devtools 不知道什麽時候回調函數實際上被調用——實質上任何在回調函數中進行的狀態的改變都是不可追蹤的。
在 mutation 中混合異步調用會導致你的程序很難調試。例如,當你調用了兩個包含異步回調的 mutation 來改變狀態,你怎麽知道什麽時候回調和哪個先回調呢?這就是為什麽我們要區分這兩個概念。在 Vuex 中,mutation 都是同步事務。
也就是說使用commit調用mutations的方法中,包含異步修改狀態的操作,也是能執行成功的;
但是在debug過程中,devtools捕捉不到異步修改的狀態的快照,導致調試困難;
因此官方提供了dispatch調用actions的方法來完成異步操作。
並且可以使用dispatch返回promise對象,在組件中完成then操作。
Hello.vue
<template> <div class="hello"> <h2>{{ msg }}</h2> <button @click="answer">修改</button> <button @click="show">查看</button> </div> </template> <script> export default { name: ‘hello‘, data () { return { newMsg:"修改中" } }, computed: { msg: function () { return this.$store.state.helloState.msg } }, methods: { answer () { this.$store.dispatch(‘helloState/setMsg‘,this.newMsg); }, show () { alert(this.$store.getters[‘helloState/msg‘](‘查看內容是:‘)); } } } </script> <style> .hello{ background-color:#E1FFFF; } </style>
組件綁定的輔助函數
也就是 mapState,mapMutations,mapGetters、mapActions 這些,一般是可以看作簡化語法的語法糖,有機會再詳細講講。
使用mapState獲取狀態的簡單實例:
修改Hello.vue
import {mapState} from ‘vuex‘; export default { // ... computed: { ...mapState ({ msg:state => state.helloState.msg }) }, }
初識vue 2.0(8):vuex進階