Vuex實踐

本文來自網易雲社區

做者:劉凌陽

前言

2017年對於Vue註定是不平凡的一年。憑藉着自身簡介、輕量、快速等特色,Vue儼然成爲最火的前端MVVM開發框架。隨着Vue2.0的release,愈來愈多的項目開始採用Vue做爲他們的前端框架。而做爲Vue生態中最重要的一環,Vuex漸漸進入你們的視野。html

數據管理模式前端

在正式開始介紹Vuex以前,有必要介紹一下數據管理模式的前世此生。vue

當你在開發應用程序時,你必定會分解出不少組件進行開發,而各個組件之間想必在邏輯上多少是有關係的。那麼組件之間的「通訊」,就成了待解決問題。之前咱們試圖用事件廣播來作,但隨之而來的問題是,在應用不斷的擴展、變化中,事件變得愈來愈複雜,愈來愈不可預料,以致於愈來愈難調試,愈來愈難追蹤錯誤。這固然不是咱們想要的,咱們但願應用的各個部分都易維護、可擴展、好調試、能預測。因而數據管理模式應運而生。git

圖1是最簡單的組件關係,b是a的子組件,而c是b的子組件。在咱們不引入任何數據管理模式以前,c組件要拿到a組件的數據只能由a先傳給b,在由b傳給c。若是組件樹變得複雜,可想而知這將是一場災難。看似嚴謹的父子結構其實嚴格限制了數據的流動方式。github

圖2是最簡單的數據管理模式,全部數據將統一交給全局store來管理。a和c組件如今直接修改store裏的數據,而且經過mapState從store中抓取本身感興趣的數據到本身的組件中。而b組件,若是它對a、c組件的數據毫無興趣,則能夠作到徹底解耦。vuex

隨着數據管理的進一步發展和演變,有一種叫單向數據流的東西冒了出來。圖3就是一個表示「單向數據流」理念的極簡示意。單向數據流要求各組件間的數據走向永遠是單向的,可預期的。你不能直接改變 store 中的狀態。改變 store 中的狀態的惟一途徑就是顯式地提交Actions。這樣使得咱們能夠方便地跟蹤每個狀態的變化,從而讓咱們可以更好地瞭解咱們的應用。緩存

此次咱們的主人公Vuex能夠說是單向數據流的最佳實踐者。前端框架

Vuex是什麼?框架

Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式。Vuex背後的基本思想,就是前面所說的單向數據流。圖4就是Vuex實現單向數據流的示意圖。異步

接下來,咱們將會更深刻地探討一些核心概念。讓咱們先從Store概念開始。

Store

每個 Vuex 應用的核心就是 store(倉庫)。「store」基本上就是一個容器,它包含着你的應用中大部分的狀態 (state) 。

安裝 Vuex 以後,讓咱們來建立一個最簡單的 store。建立過程直截了當——僅須要提供一個初始 state 對象和一些 mutation:



如今,你能夠經過 store.state 來獲取狀態對象,以及經過 store.commit 方法觸發狀態變動:


因爲 store 中的狀態是響應式的,在組件中調用 store 中的狀態簡單到僅須要在計算屬性中返回便可。觸發變化也僅僅是在組件的 methods 中提交 mutation。

State

Vuex 使用單一狀態樹——是的,用一個對象就包含了所有的應用層級狀態。至此它便做爲一個「惟一數據源 (SSOT)」而存在。單一狀態樹讓咱們可以直接地定位任一特定的狀態片斷,在調試的過程當中也能輕易地取得整個當前應用狀態的快照。

那麼咱們如何在 Vue 組件中展現狀態呢?因爲 Vuex 的狀態存儲是響應式的,從 store 實例中讀取狀態最簡單的方法就是在計算屬性中返回某個狀態:


Getter

有時候咱們須要從 store 中的 state 中派生出一些狀態,例如對列表進行過濾並計數:


若是有多個組件須要用到此屬性,咱們要麼複製這個函數,或者抽取到一個共享函數而後在多處導入它——不管哪一種方式都不是很理想。

Vuex 容許咱們在 store 中定義「getter」(能夠認爲是 store 的計算屬性)。就像計算屬性同樣,getter 的返回值會根據它的依賴被緩存起來,且只有當它的依賴值發生了改變纔會被從新計算。


Getter 會暴露爲 store.getters 對象:


Mutation

Vuex 的 store 中的狀態的惟一方法是提交 mutation。Vuex 中的 mutation 很是相似於事件:每一個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數(handler)。這個回調函數就是咱們實際進行狀態更改的地方,而且它會接受 state 做爲第一個參數,payload做爲第二個參數(額外的參數):


一條重要的原則就是要記住 mutation 必須是同步函數。  

Action

Action 相似於 mutation,不一樣在於:

    1.Action 提交的是 mutation,而不是直接變動狀態。 

    2.Action 能夠包含任意異步操做。

讓咱們來註冊一個簡單的 action:


Action 函數接受一個與 store 實例具備相同方法和屬性的 context 對象,所以你能夠調用 context.commit 提交一個 mutation,或者經過 context.state 和 context.getters 來獲取 state 和 getters。

咱們能夠在 action 內部執行異步操做:

今天的目標


這是一個記憶小遊戲,來自leftstick的vue-memory-game,github地址:https://github.com/leftstick/vue-memory-game。今天咱們就這個小遊戲來詳細講解下vuex的實現。

組件分解


咱們根據分解圖,先把要實現的組件挨個兒列出來:

  1. Game, 最外層的遊戲面板

  2. Dashboard, 上面的logo,遊戲進度,最佳戰績的容器

  3. Logo,左上角的logo

  4. MatchInfo, 正中上方的遊戲進度組件

  5. Score, 右上角的最佳戰績組件

  6. Chessboard, 正中大棋盤

  7. Card, 中間那十六個棋牌

  8. PlayStatus, 最下方的遊戲狀態信息欄

目錄結構

讓咱們聚焦紅框中關於Vuex的這一部分。接下來咱們將結合Card.vue和Chessboard.vue這兩個核心組件進行。

store/index.js


store的建立並無什麼複雜的邏輯,而state就是這個項目須要維護的整個數據。初始化cards的結構我簡要的整合了一下:


你能夠選擇初始化store的時候直接帶進去,也能夠像做者同樣從入口處reset一遍數據,這裏就不詳細展開了。

Chessboard.vue

Card.vue


我在源碼上增長了一些註釋,方便你們理解。

mapGetter和mapActions只是一些輔助函數,能夠減小一些this.$store和dispatch action之類比較重複的代碼,這些輔助函數能夠幫助vuex應用的更加簡便。

相比與這些無關緊要的噱頭,咱們更關心卡片被點擊的時候發生了什麼?this.flipCard()後數據流向了哪裏?

數據流動


當卡片被點擊時,vue component 實則 dispatch出了一個action,而咱們的數據,做爲載荷(參數),也只能隨波逐流了。

他首先來到了第一站:actions,然而actions卻說你不須要什麼異步處理,能夠去下一站了。(若是沒有異步操做,其實能夠少走一站)

 actions處理函數

數據沒有灰心,很快他就來到了mutaions。

mutaions欣喜若狂:你在這等着,待我處理好了你再上路。

 mutations處理函數

不一會,數據就改頭換面了,但如何告訴vue components我發生變化了呢?迷茫的數據找到了getter。getter哈哈大笑:你在我這的狀態存儲是響應式的,只要vue components在計算屬性中應用了你,他們就能第一時間知道你的狀態變動哦。

 

getter生成計算屬性(若是沒有派生出其餘狀態,能夠不用getter)

 components狀態更新


結尾

經過這個記憶小遊戲,但願你們對Vuex有一個基本的理解。若是你熟悉Redux的話,掌握Vuex應該不難,由於Vuex和Redux基本思想是一致的,實現方式也是大同小異。但Vuex只適用於Vue,沒有Redux那麼泛用罷了。


網易雲大禮包:https://www.163yun.com/gift


本文來自網易雲社區,經做者劉凌陽受權發佈

   


   


相關文章:
【推薦】 如何從「點子」落地到「執行」?—完整解析1個手遊傳播類mini項目的進化
【推薦】 非對稱加密與證書(上篇)
【推薦】 Wireshark對HTTPS數據的解密

相關文章
相關標籤/搜索