什麼是Vuex?javascript
官方說法:Vuex 是一個專爲 Vue.js應用程序開發的狀態管理模式。它採用集中式存儲管理應用的全部組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。html
我的理解:Vuex是用來管理組件之間通訊的一個插件vue
爲何要用Vuex?java
組件之間是獨立的,組件之間想要實現通訊,我目前知道的就只有props選項,但這也僅限於父組件和子組件之間的通訊。若是兄弟組件之間想要實現通訊呢?方法應該有。拋開怎麼實現的問題,試想一下,當作中大型項目時,面對一大堆組件之間的通訊,還有一大堆的邏輯代碼,會很苦惱,此時咱們應該吧組件之間共享的數據給拿出來,在規則下來管理這些數據,這就是Vuex的基本思想vuex
VueX的使用npm
首先須要下載 vuexapp
npm i -S vuex
而後在src文件目錄下新建一個名爲store的文件夾,爲方便引入並在store文件夾裏新建一個index.js,裏面的內容以下:異步
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store();
export default store;
接下來,在main.js裏面引入store,而後再全局注入一下,這樣一來就能夠在任何一個組件裏面使用this.$store了:ide
import store from './store'//引入store new Vue({ el: '#app', router, store,//使用store template: '<App/>', components: { App } })
再接下來vuex 的核心來了,vuex的五大核心---state,getter,mutation,action,module函數
state就是一個數據倉庫,存放數據的,
回到store文件的indexjs裏面,咱們先聲明一個state變量,並賦值一個空對象給它,裏面隨便定義兩個初始屬性值;而後再在實例化的Vuex.Store裏面傳入一個空對象,並把剛聲明的變量state仍裏面:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state = { //要設置的全局訪問的state對象 showFooter: true, changableNum: 0 //要設置的初始屬性值 }; const store = new Vuex.Store({ state }); export default store;
如今你已經可使用this.$store.state.showFooter和this.$store.state.changebleNum在任何一個組件裏面獲取showFooter和changebleNum的值。但這不是很完美的方法,vuex官方API提供了一個getters屬性,和vue計算屬性computed同樣,來實時監聽state值的變化,並把它扔進Vuex.Store裏面,具體如此:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state = { //要 設置的全局訪問的state對象 showFooter: true, changableNum: 0 //要設置的初始屬性值 }; const getters = { //實時 監聽state值的變化(最新狀態) isShow(state) { //方法名隨意,主要 是來承載變化的showFooter的值 return state.showFooter //在組件中能夠用 this.$store.getters.isShow 來獲取它的return值 }, getChangedNum() { // 方法名隨意, 主要是用來承載變化的changableNum的值 return state.changableNum //在組件中能夠用 this.$store.getters.getChangedNum 來獲取它的return值 } } const store = new Vuex.Store({ state, getters }); export default store;
光有定義的state的初始值,不改變它不是咱們想要的需求,接下來要說的就是mutations了,mutattions也是一個對象,這個對象裏面能夠放改變state的初始值的方法,具體的用法就是給裏面的方法傳入參數state或額外的參數,而後利用vue的雙向數據驅動進行值的改變,一樣的定義好以後也把這個mutations扔進Vuex.Store裏面,以下:
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要設置的全局訪問的state對象 showFooter: true, changableNum:0 //要設置的初始屬性值 }; const getters = { //實時監聽state值的變化(最新狀態) isShow(state) { //承載變化的showFooter的值 return state.showFooter }, getChangedNum(){ //承載變化的changebleNum的值 return state.changableNum } }; const mutations = { show(state) { //自定義改變state初始值的方法,這裏面的參數除了state以外還能夠再傳額外的參數(變量或對象); state.showFooter = true; }, hide(state) { //同上 state.showFooter = false; }, newNum(state,sum){ //同上,這裏面的參數除了state以外還傳了須要增長的值sum state.changableNum+=sum; } }; const store = new Vuex.Store({ state, getters, mutations }); export default store;
這時候你徹底能夠用this. $store.commit('show)或this. $store.commit("hide')以及this. $store. commit("newNum',6)在別的組件裏面進行改變showfooter和changebleNum的值了,這不是理想的改變值的方式;由於在Vuex中,mutations裏面的方法都是同步事務,意思就是說:好比這裏的一個this.$store.commit( newNum' sum)方法,兩個組件裏用執行獲得的值,每次都是同樣的,這樣確定不是理想的需求。
好在vuex官方API還提供了一個actions,這個actions也是個對象變量,最大的做用就是面的Action方法
能夠包含任意異步操做,這裏面的方法是睞異步觸發mutations裏面的方法,actions裏面自定 義的函數接
收一個context參數和要變化的形參, context 與store實例具備相同的方法和屬性,因此它能夠執行
context.commit(' "),而後也不要忘了把它也扔進Vuex.Store裏面
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); const state={ //要設置的全局訪問的state對象 showFooter: true, changableNum:0 //要設置的初始屬性值 }; const getters = { //實時監聽state值的變化(最新狀態) isShow(state) { //承載變化的showFooter的值 return state.showFooter }, getChangedNum(){ //承載變化的changebleNum的值 return state.changableNum } }; const mutations = { show(state) { //自定義改變state初始值的方法,這裏面的參數除了state以外還能夠再傳額外的參數(變量或對象); state.showFooter = true; }, hide(state) { //同上 state.showFooter = false; }, newNum(state,sum){ //同上,這裏面的參數除了state以外還傳了須要增長的值sum state.changableNum+=sum; } }; const actions = { hideFooter(context) { //自定義觸發mutations裏函數的方法,context與store 實例具備相同方法和屬性 context.commit('hide'); }, showFooter(context) { //同上註釋 context.commit('show'); }, getNewNum(context,num){ //同上註釋,num爲要變化的形參 context.commit('newNum',num) } }; const store = new Vuex.Store({ state, getters, mutations, actions }); export default store;
而在外部組件裏進行全局執行actions裏面方法的時候,你只須要用執行
this.$store.dispatch('hideFooter')
或this.$store.dispatch('showFooter')
以及this.$store.dispatch('getNewNum',6) //6要變化的實參
這樣就能夠全局改變改變showfooter或changebleNum的值了,以下面的組件中,需求是跳轉組件頁面後,根據當前所在的路由頁面進行隱藏或顯示頁面底部的tab選項卡
<template> <div id="app"> <router-view/> <FooterBar v-if="isShow" /> </div> </template> <script> import FooterBar from '@/components/common/FooterBar' import config from './config/index' export default { name: 'App', components:{ FooterBar:FooterBar }, data(){ return { } }, computed:{ isShow(){ return this.$store.getters.isShow; } }, watch:{ $route(to,from){ //跳轉組件頁面後,監聽路由參數中對應的當前頁面以及上一個頁面 console.log(to) if(to.name=='book'||to.name=='my'){ // to.name來獲取當前所顯示的頁面,從而控制該顯示或隱藏footerBar組件 this.$store.dispatch('showFooter') // 利用派發全局state.showFooter的值來控制 }else{ this.$store.dispatch('hideFooter') } } } } </script> }else{ this.$store.dispatch('hideFooter') } } } } </script>