承接上文vue2.0一塊兒在懵逼的海洋裏越陷越深(三)
前面一篇講了vue-router的router-link
,
有讀者說但願能先看到vuex的文章
其實vuex在個人vue2.0的demo裏已經在使用了
想一想確實應該先來點vuex的了,由於有些有關的狀態管理急需vuex的加入
好,那麼此次就先上vuex吧!前端
OK!先介紹下vuex
vuex是vuejs的狀態管理方案
由於vuex有些複雜,通常應用在較複雜的狀態環境下,若是是比較簡單的應用就不須要安裝vuex了vue
如上圖所示是vuex單向數據流的流程git
我知道,若是是第一次接觸這玩意,到這就懵逼了,就像我第一次看文檔同樣 es6
下面解釋下State
前面說了vuex是vuejs的狀態管理方案,這裏的狀態就是圖中的state
在平時寫寫前端的過程當中,都會涉及到狀態的問題,
好比你看到了一篇文章寫的不錯,就想要收藏,
而後又對做者有些興趣,因而又加了關注,固然這些最後都是須要前端來表達出來
這裏面就涉及了兩個狀態就是收藏與關注
這裏的收藏與關注咱們能夠將其用一個變量來表示,固然如這兩種只存在兩個相對狀態的用布爾值(bool
)來表示就能夠了github
而後是view
view
就是視圖,也就是前端所寫的頁面,前面的state
就能夠在view
裏面獲得體現,便是你看到的是否關注了做者ajax
然後是Actions
Actions
是View
用來改變State
的方法,經過改變State
從而改變View
的顯示vue-router
這麼說有些抽象,打個比方
假設學生小明生病了
小明要向班主任請假(小明就是View
,小明想改變本身的顯示狀態,從上學狀態變成請假狀態)
因而小明口頭向班主任請假(請假就是Actions
,小明經過請假這一個方法達到請假的目的)
班主任批准,小明請假成功(班主任就是State
的提供者,小明經過請假方法使班主任改變小明的State
狀態)
着也就解釋了爲何要有這個流程,有了這個流程就能夠統一管理各個view
的各個狀態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庫地址
項目結構:
├── 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庫里加個星,若是有問題能夠在下方評論裏討論討論?