vue2.0一起在懵逼的海洋里越陷越深(四)


前言

承接上文vue2.0一起在懵逼的海洋里越陷越深(三)
前面一篇講了vue-router的router-link,
有讀者說希望能先看到vuex的文章
其實vuex在我的vue2.0的demo里已經在使用了
想想確實應該先來點vuex的了,因為有些有關的狀態管理急需vuex的加入
好,那么這次就先上vuex吧!

正文

OK!先介紹下vuex
vuex是vuejs的狀態管理方案
因為vuex有些復雜,一般應用在較復雜的狀態環境下,如果是比較簡單的應用就不需要安裝vuex了

vuex單向數據流

vuex單向數據流

如上圖所示是vuex單向數據流的流程

** 我知道,如果是第一次接觸這玩意,到這就懵逼了,就像我第一次看文檔一樣 **


** 下面解釋下State **
前面說了vuex是vuejs的狀態管理方案,這里的狀態就是圖中的state
在平時寫寫前端的過程中,都會涉及到狀態的問題,
比如你看到了一篇文章寫的不錯,就想要收藏,
然后又對作者有些興趣,于是又加了關注,當然這些最后都是需要前端來表達出來
這里面就涉及了兩個狀態就是收藏與關注
這里的收藏與關注我們可以將其用一個變量來表示,當然如這兩種只存在兩個相對狀態的用布爾值(bool)來表示就可以了

** 然后是view **
view就是視圖,也就是前端所寫的頁面,前面的state就可以在view里面得到體現,即是你看到的是否關注了作者

** 而后是Actions **
ActionsView用來改變State的方法,通過改變State從而改變View的顯示

這么說有些抽象,打個比方
假設學生小明生病了
小明要向班主任請假(小明就是View,小明想改變自己的顯示狀態,從上學狀態變成請假狀態)
于是小明口頭向班主任請假(請假就是Actions,小明通過請假這一個方法達到請假的目的)
班主任批準,小明請假成功(班主任就是State的提供者,小明通過請假方法使班主任改變小明的State狀態)
著也就解釋了為什么要有這個流程,有了這個流程就可以統一管理各個view的各個狀態

vuex多個組件共享狀態

先貼個流程圖,懵逼是沒啥關系的


vuex多個組件共享狀態

可以看到這一張圖比前面一張復雜了許多,其實里面的實線框就是上圖的升級版

情況是這樣,原來小明學校里這段時間許多同學得了流感,于是同學們一窩蜂的要求請假,
學校里因為人太多,又沒有一個記錄,人數清點不過來了,于是班主任要求請假必須提交請假條

好的,來解釋下上圖內的實線部分,之前的View在這里改名成了Vue Components,代表了多個組件(這里即是指多個同學)
包括小明在內的多個同學Vue Components都得了流感,一起想要請假Actions(他們即將共享一個請假狀態),小明代表多個同學寫了一張請假條交給班主任(State提供者)簽字同意(簽字同意這個動作就是Mutations,觸發了State的改變),班主任同意后統一給他們改變了State(請假成功)

這里的多了一個同步與異步的區別,其中Mutations只受理同步處理,而Actions就是執行異步操作的函數,作為代價,Actions不再能直接觸發改變State狀態,而是需通過Mutations來觸發State的改變

情況是這樣,因為不只是一個班的學生得了流感,請假的人比較多,學校Backend API需要做一個統計,于是請假需要得到學校專門的請假條的并通過學校簽字才能生效,這里就有了虛線部分。
請假Actions改變State的方法不再是僅僅班主任簽字就可以了,而是需要通過學校這個前提,于是Actions就變成了一個異步請求,需要得到學校Backend API的專門的請假條和簽字同意后,才能向班主任提交改變State的申請

這里想要表達的意思就是,Vue Components改變自身狀態需要通過Actions(有需要的話要向后端接口Backend API發送請求)來操作Mutations改變State從而改變自身狀態。
至于圖中沒有說到的Devtools是一個開發者工具,是一個便于查看和管理vue應用以及vuex狀態的瀏覽器插件。
你可以在里面看到你vue對象和vuex每一次的commit,commit后面會說到。還有你當前的應用狀態

devtools

附上一個devtools庫地址

架構vuex

項目結構:

├── main.js
├── App.vue
├── components
│   ├── Home.vue
│   └── ...
└── store
    ├── index.js          # 組裝模塊并導出 store 的地方
    ├── actions.js        # 根級別的 action
    ├── mutations.js      # 根級別的 mutation
    ├── types.js          # mutation命名空間
    └── modules
        ├── demo.js       # demo模塊
        └── status.js     # 全局應用狀態模塊

結構可以根據個人需要進行調整

** 下面開始構建store/index.js **
當然在這之前,如果沒有安裝vuex的需要先安裝

npm i vuex -S

由于vuex的內容太多,這里先說基礎用法
首先為store/index.js編寫內容

import Vue from 'vue'
// 導入vue
import Vuex from 'vuex'
// 導入vuex

import status from './modules/status'
// 導入status模塊(這是我管理全局應用狀態的模塊)
import demo from './modules/demo'
// 導入demo模塊(這個的部分演示可以在http://vue2.leenty.com/demo/vuex_state/里看到)

Vue.use(Vuex)
// 告訴vue將要使用vuex

const debug = process.env.NODE_ENV !== 'production'
// env里去獲取當前的環境是否需要開啟嚴格模式
// 在發布環境開啟嚴格模式會造成性能上不必要的損失

export default new Vuex.Store({
// 默認導出vuex模塊
  modules: {
  // 導入模塊
    status,
    demo
  },
  strict: debug
  // 是否開啟嚴格模式
})

** 構建state模塊 **
這里以demo.js為例

import * as types from '../types'
// 導入mutations的命名空間

const state = {
// 定義state
  demoFollow: false,
  // 這里模擬的是關注的狀態,布爾值表示是否關注
  demoFollowPending: false
  // 是否在請求中(actions是否在執行異步操作)
}

const getters = {
// 定義getters, getters是對state的擴展,可以以state衍生出其他狀態
  demoFollowStatus: state => state.demoFollow ? '已關注' : '未關注'
  // demoFollowStatus是demoFollow的衍生量,將原來的布爾值映射為'已關注' : '未關注'
}

const mutations = {
// 只有mutations才能操作改變state,mutations是同步執行的
// 所以有關異步的操作請放在actions里執行
  [types.DEMO__VUEX_FOLLOW] (state, status = NaN) {
  // 使用預定義好的名字來寫mutations方法
    state.demoFollow = isNaN(status) ? !state.demoFollow : status
  },
  [types.DEMO__VUEX_FOLLOW_PENDING] (state, status = NaN) {
  // 這里對status傳值做了審查,如沒有傳,則對要改變的布爾值進行取反操作
    state.demoFollowPending = isNaN(status) ? !state.demoFollowPending : status
  }
}

const actions = {
// actions是可以執行異步操作的,操作完畢后觸發mutations里的方法去改變state的狀態
  demoFollowAjax ({commit}, status) {
    commit(types.DEMO__VUEX_FOLLOW_PENDING)
    // 在異步操作前通過mutations告訴應用,現在正在進行異步操作
    setTimeout(() => {
      // 利用延時函數模擬異步的ajax操作
      commit(types.DEMO__VUEX_FOLLOW_PENDING)
      // commit 是在actions里用來觸發mutations的方法
      // 告訴應用,異步操作結束
      commit(types.DEMO__VUEX_FOLLOW, status)
      // 為關注按鈕賦予新的狀態
    }, 2000)
  }
}

export default {
// 導出整個demo模塊
  state,
  getters,
  actions,
  mutations
}

** 這里解釋下mutations里的方法的奇怪寫法,我知道如果對es6于法了解不多這里是會懵逼的 **

const mutations = {
  [types.DEMO__VUEX_FOLLOW] (state, status = NaN) {
    state.demoFollow = isNaN(status) ? !state.demoFollow : status
  }
}

這是對象內方法的簡化寫法,其中types.DEMO__VUEX_FOLLOW是在types.js里預定義的,內容如下

export const DEMO__VUEX_FOLLOW = 'DEMO__VUEX_FOLLOW'
export const DEMO__VUEX_FOLLOW_PENDING = 'DEMO__VUEX_FOLLOW_PENDING'
// 其實就是字符串集合,最后用 import * as types from '../types' 方法導入vuex模塊里
// 就變成了一個types對象

上例中全部展開是這樣的

const mutations = {
  [types.DEMO__VUEX_FOLLOW]: (state, status = NaN) => {
  // [types.DEMO__VUEX_FOLLOW]是提取types.DEMO__VUEX_FOLLOW的值的一種方式
  // 在這里[types.DEMO__VUEX_FOLLOW]提取出來就是types.js里預定義的'DEMO__VUEX_FOLLOW'
    if (isNaN(status){
      state.demoFollow = !state.demoFollow
    } else {
      state.demoFollow = status
    }
  }
}

好,到此為止,vuex就已經建立好了,下面就說如何使用了

應用狀態的使用與改變

vuex提供了4個輔助函數

import { mapState, mapGetters, mapActions, mapMutations } from 'vuex'

是分別用來獲取State, Getters, Actions, Mutations的map方法
在vue Components里面你可以以這樣的方式來導入需要使用的方法

這4個方法擁有統一的參數格式以及一個統一的返回格式
可以傳入一個數組

mapGetters(['demoFollowStatus'])
// 此方法導出的是一個Getters對象
mapGetters({
  demoFollow: 'demoFollowStatus'
})
// 可以通過傳入對象的形式來改變得到的getters方法名

同理,不同的map方法會導出各自的方法
其中mapState, mapGetters將會導出適用于computed的方法
mapMutations, mapActions將會導出適用于methods的方法

這里以一個demo組件為例DemoVuexState.vue

import { mapState, mapGetters, mapMutations, mapActions } from 'vuex'
export default {
  data () {
    return {
    }
  },
  computed: {
  // vue的計算屬性,計算屬性內方法的私有變量變動會觸發這個屬性的重新計算
    ...mapState({
      mapStateFollow: ({demo}) => demo.demoFollow,
      mapStateFollowPending: ({demo}) => demo.demoFollowPending
    }),
    // mapState()直接讀取State里的狀態內容
    ...mapGetters(['demoFollowStatus'])
    // mapGetters()通過getters轉化state從而得到你想要的內容
  },
  methods: {
  // vue的方法,可以是一個事件的方法,也可以是一個vuex的方法,也可以是一個普通函數
    ...mapMutations(['DEMO__VUEX_FOLLOW']),
    // 同步的改變狀態
    ...mapActions(['demoFollowAjax'])
    // 異步的改變狀態
  }
}

這段代碼是一個demo里的片段,效果大家可以看這個呆萌,如果開心了可以在github庫里加個星,如果有問題可以一起在下方評論里討論討論??

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 就在今年的10月份,Vue2.0發布啦,來懵逼的海洋里一起下沉吧! 前段陣子都沒有發隨筆,一方面要準備一場考試,另...
    leenty閱讀 1,598評論 4 22
  • vuex 場景重現:一個用戶在注冊頁面注冊了手機號碼,跳轉到登錄頁面也想拿到這個手機號碼,你可以通過vue的組件化...
    sunny519111閱讀 8,035評論 4 111
  • 承接上文vue2.0一起在懵逼的海洋里越陷越深(二)前面寫了vue-router組件的初步用法,原來這次想寫vue...
    leenty閱讀 1,595評論 4 9
  • 參考書目:《人生定位:特勞特教你營銷自己》[美] 阿爾·里斯、杰克·特勞特 學會“靠”別人 一看到這個說法,我的第...
    仲夏夜之夢123閱讀 209評論 2 7
  • 愛是什么 愛是怦然的心跳 愛是掌心的細汗 愛是眺望、是念想, 是源源不斷的思緒; 愛是歡騰、是跳躍, 是上天又入地...
    LotusLi閱讀 677評論 0 51