vue2.0一塊兒在懵逼的海洋裏越陷越深(四)

前言

承接上文vue2.0一塊兒在懵逼的海洋裏越陷越深(三)
前面一篇講了vue-router的router-link,
有讀者說但願能先看到vuex的文章
其實vuex在個人vue2.0的demo裏已經在使用了
想一想確實應該先來點vuex的了,由於有些有關的狀態管理急需vuex的加入
好,那麼此次就先上vuex吧!前端

正文

OK!先介紹下vuex
vuex是vuejs的狀態管理方案
由於vuex有些複雜,通常應用在較複雜的狀態環境下,若是是比較簡單的應用就不須要安裝vuex了vue

vuex單向數據流

vuex單向數據流

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

我知道,若是是第一次接觸這玩意,到這就懵逼了,就像我第一次看文檔同樣
clipboard.pnges6

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

而後是view
view就是視圖,也就是前端所寫的頁面,前面的state就能夠在view裏面獲得體現,便是你看到的是否關注了做者ajax

然後是Actions
ActionsView用來改變State的方法,經過改變State從而改變View的顯示vue-router

這麼說有些抽象,打個比方
假設學生小明生病了
小明要向班主任請假(小明就是View,小明想改變本身的顯示狀態,從上學狀態變成請假狀態)
因而小明口頭向班主任請假(請假就是Actions,小明經過請假這一個方法達到請假的目的)
班主任批准,小明請假成功(班主任就是State的提供者,小明經過請假方法使班主任改變小明的State狀態)
着也就解釋了爲何要有這個流程,有了這個流程就能夠統一管理各個view的各個狀態vuex

vuex多個組件共享狀態

先貼個流程圖,懵逼是沒啥關係的
vuex多個組件共享狀態shell

能夠看到這一張圖比前面一張複雜了許多,其實裏面的實線框就是上圖的升級版npm

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

好的,來解釋下上圖內的實線部分,以前的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庫里加個星,若是有問題能夠在下方評論裏討論討論?

相關文章
相關標籤/搜索