用過vue的朋友大概對vuex也不陌生,vuex的官方解釋是專為 Vue.js 應用程序開發的狀態管理模式。它采用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。說的簡單點就是對vue的狀態進行統一管理,如下圖介紹了其管理模式:

最簡單的使用方法長這樣的:
// 如果在模塊化構建系統中,請確保在開頭調用了 Vue.use(Vuex) const store = new Vuex.Store({ state: { count: 0 }, mutations: { increment (state) { state.count++ } } })
如果項目中需要管理的狀態很多,也可以將這些方法按文件分開,最后掛載在index文件下:
// state.js export default { total: 0 } // mutaction.js export default { add(state){ state++ } } // action.js export default { addAsync(context){ setTimeout(() => { context.commit('add'); }, 1000); } }
最后統一導入到index.js
// index.js import Vue from 'vue'; import Vuex from 'vuex'; import { state } from './state'; import mutations from './mutation'; import actions from './action'; Vue.use(Vuex); export default new Vuex.Store({ state, mutations, actions, });
完畢,這就是基本的vuex的開發模式。接下來,我不會過多介紹vuex的用法,而是介紹如何基於typescript,用class的方式來使用vue和vuex進行項目開發,相信使用過react的朋友們對class的寫法不會陌生,那就讓我們開始吧!
為了省去一些配置上的麻煩,我們直接采用vue-cli3來搭建項目。在創建項目的時候選中typescript即可。

創建完項目之后,我們對項目結構進行調整,使其更易於維護和管理,如下:

接下來開始我們的代碼編寫,首先關注store目錄,這是我們管理項目狀態的地方,我們將state改寫成typescript的方式:
export interface State { name: string; total: number; isLogin: boolean; postList: object[]; } export const state: State = { name: '', total: 0, isLogin: false, postList: [], };
如果對typescript不熟悉的同學,可以移步到typescript官網去了解基本用法。
action文件和之前沒有太大變化,只是增加了類型定義和參數
export default { asyncAdd(context: any, paylod: any) { setTimeout(() => { context.commit('add', paylod.num); }, 1000); }, };
下面是mutaction文件:
import { State } from './state'; export default { add(state: State, payload: any) { payload ? (state.total += payload) : state.total++; }, };
說到這里,有必要簡單講解一下action和mutaction的區別:
Action 類似於 mutation,不同在於:
- Action 提交的是 mutation,而不是直接變更狀態。Action 可以包含任意異步操作。
- 說簡單點就是mutation用於同步執行,action用於異步執行,可以多重分發mutation。
完成了這些,vuex的工作大致告於段落,接下來我們關注的重點就是頁面組件和如何在組件中使用vuex。
// home.vue <template> <div class="home"> <img alt="Vue logo" src="../assets/logo.png"> <HelloWorld :msg="name" /> <div @click="onclick">{{name}}</div> <div @click="add">同步增加總數:{{total}}</div> <div @click="addAsync(1)">異步增加總數:{{total}}</div> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import { mapMutations } from 'vuex'; import HelloWorld from '@/components/HelloWorld.vue'; // @ is an alias to /src @Component({ components: { HelloWorld, }, }) export default class Home extends Vue { public name: string = 'xujiang'; public onclick(): void { this.name = 'hello world'; } public add() { this.$store.commit('add'); } public addAsync(num: any) { this.$store.dispatch('asyncAdd', {num}); } get total(): void { return this.$store.state.total; } } </script>
相信用過react的朋友對這種寫法並不陌生,其實vue完全可以將模版寫法改寫成jsx的方式,就好比寫react的jsx文件一樣,后面我會推出一篇文章,專門介紹如何使用jsx+class的方式開發vue組件。
vue-cli3已經為我們安裝了是支持class和裝飾器的模塊vue-property-decorator,當然想自己配置的朋友也可以通過webpack自己配置,無限可能,我也會在后面推出關於webpack的文章,教大家如何玩轉webpack4.0。
使用class方式創建組件和傳統的方式有點區別:1.一般我們定義data作為數據源,在class中我們可以直接定義屬性,即可作為初始數據;2.vue實例方法一般定義在methods中,用類組件時,可以直接使用組件方法。
最后,我們可以用vuex提供的commit和dispatch來觸發我們狀態的變化,至此,一個class版的vue組件就寫好啦,如有不懂的地方或者文章沒有考慮到的地方,歡迎隨時指出。歡迎交流更多前端知識,經驗。
接下來即將推出的文章:
1.玩轉webpack4.0
2.typescript實用知梳理
3.react+redux+redux+trunk+immutable實戰總結