1. 程式人生 > >初識vue 2.0(8):vuex進階

初識vue 2.0(8):vuex進階

rom 註冊 簡單實例 imp module aps cti 函數 maps

主要講三部分內容:

  1. vuex模塊化
  2. vuex命名空間
  3. mutations和actions

模塊化

由於使用單一狀態樹,應用的所有狀態會集中到一個比較大的對象,當應用變得非常復雜時,store 對象就有可能變得相當臃腫。

為了解決以上問題,Vuex 允許我們將 store 分割成模塊(module),每個模塊擁有自己的 state、mutation、action、getter。

因此,創建一個store目錄,用來存儲狀態。

store/
|_ index.js
|_ helloModule.js
|_ gameModule.js

在index.js中導出組件,並在main.js中註冊

index.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 = new
Vuex.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進階