一般情況下康嘉,在SPA單頁(yè)面組件的開(kāi)發(fā)中亭珍,都是使用組件化的方式來(lái)進(jìn)行開(kāi)發(fā)枝哄,使得項(xiàng)目更加容易管理和維護(hù)挠锥。雖然組件化開(kāi)發(fā)有其優(yōu)點(diǎn),但是缺點(diǎn)也存在粱侣,比如組件與組件之間的數(shù)據(jù)聯(lián)動(dòng)以及管理齐婴,父子組件傳值還好說(shuō),組件與組件的傳值那就麻煩了柠偶,而且不容易對(duì)數(shù)據(jù)進(jìn)行管理诱担。于是在這種情況下蔫仙,vuex出來(lái)了,我們可以先到官方網(wǎng)站看vuex的具體介紹秦效。
用大白話說(shuō)就是vuex是一個(gè)公共數(shù)據(jù)存放倉(cāng)庫(kù)涎嚼,其中的數(shù)據(jù)是和N個(gè)組件共享的法梯,當(dāng)在某個(gè)組件內(nèi)改變了該數(shù)據(jù),那么另一些與之關(guān)聯(lián)的組件數(shù)據(jù)也會(huì)發(fā)生變化夜惭。
首先在 vue 2.0+ 你的vue-cli項(xiàng)目中安裝 vuex :
npm install vuex --save
然后 在src文件目錄下新建一個(gè)名為store的文件夾铛绰,為方便引入并在store文件夾里新建一個(gè)index.js,里面的內(nèi)容如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const store = new Vuex.Store();
export default store;
接下來(lái)捂掰,在 main.js里面引入store,然后再全局注入一下鸥昏,這樣一來(lái)就可以在任何一個(gè)組件里面使用this.$store了:
import store from './store'//引入store
new Vue({
el: '#app',
router,
store,//使用store
template: '<App/>',
components: { App }
})
說(shuō)了上面的前奏之后吏垮,接下來(lái)就是納入正題了膳汪,就是開(kāi)篇說(shuō)的state的玩法九秀。回到store文件的index.js里面,我們先聲明一個(gè)state變量,并賦值一個(gè)空對(duì)象給它晴音,里面隨便定義兩個(gè)初始屬性值锤躁;然后再在實(shí)例化的Vuex.Store里面?zhèn)魅胍粋€(gè)空對(duì)象或详,并把剛聲明的變量state仍里面:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={//要設(shè)置的全局訪問(wèn)的state對(duì)象
showFooter: true,
changableNum:0
//要設(shè)置的初始屬性值
};
const store = new Vuex.Store({
state
});
export default store;
實(shí)際上做完上面的三個(gè)步驟后霸琴,已經(jīng)可以用this.store.state.changebleNum在任何一個(gè)組件里面獲取showfooter和changebleNum定義的值了,但這不是理想的獲取方式澎迎;vuex官方API提供了一個(gè)
getters
选调,和vue計(jì)算屬性computed一樣,來(lái)實(shí)時(shí)監(jiān)聽(tīng)state值的變化(最新?tīng)顟B(tài))哮洽,并把它也仍進(jìn)Vuex.Store里面鸟辅,具體看下面代碼:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問(wèn)的state對(duì)象
showFooter: true,
changableNum:0
//要設(shè)置的初始屬性值
};
const getters = { //實(shí)時(shí)監(jiān)聽(tīng)state值的變化(最新?tīng)顟B(tài))
isShow(state) { //方法名隨意,主要是來(lái)承載變化的showFooter的值
return state.showFooter
},
getChangedNum(){ //方法名隨意,主要是用來(lái)承載變化的changableNum的值
return state.changebleNum
}
};
const store = new Vuex.Store({
state,
getters
});
export default store;
光有定義的state的初始值剔桨,不改變它不是我們想要的需求徙融,接下來(lái)要說(shuō)的就是mutations
了欺冀,mutattions
也是一個(gè)對(duì)象,這個(gè)對(duì)象里面可以放改變state的初始值的方法饺饭,具體的用法就是給里面的方法傳入?yún)?shù)state或額外的參數(shù),然后利用vue的雙向數(shù)據(jù)驅(qū)動(dòng)進(jìn)行值的改變瘫俊,同樣的定義好之后也把這個(gè)mutations
扔進(jìn)Vuex.Store里面,如下:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問(wèn)的state對(duì)象
showFooter: true,
changableNum:0
//要設(shè)置的初始屬性值
};
const getters = { //實(shí)時(shí)監(jiān)聽(tīng)state值的變化(最新?tīng)顟B(tài))
isShow(state) { //承載變化的showFooter的值
return state.showFooter
},
getChangedNum(){ //承載變化的changebleNum的值
return state.changableNum
}
};
const mutations = {
show(state) { //自定義改變state初始值的方法骂蓖,這里面的參數(shù)除了state之外還可以再傳額外的參數(shù)(變量或?qū)ο?;
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){ //同上登下,這里面的參數(shù)除了state之外還傳了需要增加的值sum
state.changableNum+=sum;
}
};
const store = new Vuex.Store({
state,
getters,
mutations
});
export default store;
這時(shí)候你完全可以用 this.$store.commit('show')
或 this.$store.commit('hide')
以及 this.$store.commit('newNum',6)
在別的組件里面進(jìn)行改變showfooter和changebleNum的值了被芳,但這不是理想的改變值的方式畔濒;因?yàn)樵?Vuex 中篓冲,mutations
里面的方法 都是同步事務(wù)宠哄,意思就是說(shuō):比如這里的一個(gè)this.$store.commit('newNum',sum)
方法,兩個(gè)組件里用執(zhí)行得到的值,每次都是一樣的诽俯,這樣肯定不是理想的需求
好在vuex官方API還提供了一個(gè)actions
承粤,這個(gè)actions
也是個(gè)對(duì)象變量,最大的作用就是里面的Action方法 可以包含任意異步操作仙粱,這里面的方法是用來(lái)異步觸發(fā)mutations
里面的方法彻舰,actions
里面自定義的函數(shù)接收一個(gè)context參數(shù)和要變化的形參,context與store實(shí)例具有相同的方法和屬性隔心,所以它可以執(zhí)行context.commit(' ')
,然后也不要忘了把它也扔進(jìn)Vuex.Store里面:
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
const state={ //要設(shè)置的全局訪問(wèn)的state對(duì)象
showFooter: true,
changableNum:0
//要設(shè)置的初始屬性值
};
const getters = { //實(shí)時(shí)監(jiān)聽(tīng)state值的變化(最新?tīng)顟B(tài))
isShow(state) { //承載變化的showFooter的值
return state.showFooter
},
getChangedNum(){ //承載變化的changebleNum的值
return state.changableNum
}
};
const mutations = {
show(state) { //自定義改變state初始值的方法硬霍,這里面的參數(shù)除了state之外還可以再傳額外的參數(shù)(變量或?qū)ο?;
state.showFooter = true;
},
hide(state) { //同上
state.showFooter = false;
},
newNum(state,sum){ //同上唯卖,這里面的參數(shù)除了state之外還傳了需要增加的值sum
state.changableNum+=sum;
}
};
const actions = {
hideFooter(context) { //自定義觸發(fā)mutations里函數(shù)的方法,context與store 實(shí)例具有相同方法和屬性
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;
而在外部組件里進(jìn)行全局執(zhí)行actions里面方法的時(shí)候撩轰,你只需要用執(zhí)行
this.$store.dispatch('hideFooter')
或this.$store.dispatch('showFooter')
以及this.$store.dispatch('getNewNum'堪嫂,6)
//6要變化的實(shí)參
這樣就可以全局改變改變showfooter或changebleNum的值了木柬,如下面的組件中,需求是跳轉(zhuǎn)組件頁(yè)面后,根據(jù)當(dāng)前所在的路由頁(yè)面進(jìn)行隱藏或顯示頁(yè)面底部的tabs選項(xiàng)卡
<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){ //跳轉(zhuǎn)組件頁(yè)面后眉枕,監(jiān)聽(tīng)路由參數(shù)中對(duì)應(yīng)的當(dāng)前頁(yè)面以及上一個(gè)頁(yè)面
console.log(to)
if(to.name=='book'||to.name=='my'){ // to.name來(lái)獲取當(dāng)前所顯示的頁(yè)面恶复,從而控制該顯示或隱藏footerBar組件
this.$store.dispatch('showFooter') // 利用派發(fā)全局state.showFooter的值來(lái)控制 }else{
this.$store.dispatch('hideFooter')
}
}
}
}
</script>
}else{
this.$store.dispatch('hideFooter')
}
}
}
}
</script>
至此就可以做到一呼百應(yīng)的全局響應(yīng)狀態(tài)改變了!