Vuex的初探與實(shí)戰(zhàn)小結(jié)
1.背景
最近在做一個(gè)單頁(yè)面的管理后臺(tái)項(xiàng)目,為了提高開(kāi)發(fā)效率,使用了Vue框架來(lái)開(kāi)發(fā)。為了使各個(gè)部分的功能,獨(dú)立結(jié)構(gòu)更加清晰,于是就拆分了很多組件,但是組件與組件之間數(shù)據(jù)共享成了一個(gè)問(wèn)題,父子組件實(shí)現(xiàn)起來(lái)相對(duì)簡(jiǎn)單,prop,$emit,$on就能搞定。除此之外,有很多兄弟組件和跨多級(jí)組件,實(shí)現(xiàn)起來(lái)過(guò)程繁瑣,在多人協(xié)同開(kāi)發(fā)上,不利于統(tǒng)一管理,于是,開(kāi)始了Vue的生態(tài)之一的Vux實(shí)踐之旅。
2.概述
每一個(gè) Vuex 應(yīng)用的核心就是 store(倉(cāng)庫(kù))?!皊tore”基本上就是一個(gè)容器,它包含著你的應(yīng)用中大部分的狀態(tài) (state)。
Vuex 和單純的全局對(duì)象有以下兩點(diǎn)不同:
1.Vuex 的狀態(tài)存儲(chǔ)是響應(yīng)式的。當(dāng) Vue 組件從 store 中讀取狀態(tài)的時(shí)候,若 store 中的狀態(tài)發(fā)生變化,那么相應(yīng)的組件也會(huì)相應(yīng)地得到高效更新;2.你不能直接改變 store 中的狀態(tài)。改變 store 中的狀態(tài)的唯一途徑就是顯式地提交 (commit) mutation。這樣使得我們可以方便地跟蹤每一個(gè)狀態(tài)的變化,從而讓我們能夠?qū)崿F(xiàn)一些工具幫助我們更好地了解我們的應(yīng)用
3.安裝使用
3.1.使用Vue-cli開(kāi)發(fā)安裝vue包
cnpm install vuex --save
3.2.在src目錄下創(chuàng)建store文件夾并創(chuàng)建index.js如下(src/store/index.js)
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex);
export default new Vuex.Store({
state: {
},
getters: {
},
mutations: {
},
actions: {
}
});
然后在src文件下的main.js中使用
import Vue from 'vue'
import App from './App'
import store from './store'
Vue.config.productionTip = false
new Vue({
el: '#app',
store,
components: { App },
template: '<App/>'
})
4.用法簡(jiǎn)介
4.1.state
state是保存共享數(shù)據(jù)的,現(xiàn)在改store/index.js如下:
state: {
count:0
},
在components目錄下創(chuàng)建Index.vue如:
<template>
<div class="index">
{{count}}
</div>
</template>
<script>
export default {
name: "index",
computed:{
count(){
return this.$store.state.count;
}
}
}
</script>
結(jié)果如下:

我們可以通過(guò)組件的計(jì)算屬性來(lái)保存state里面的值,那么問(wèn)題來(lái)了,如果store太多的話,我們組件里面的計(jì)算屬性豈不是成了這個(gè)樣子:
computed:{
count(){
return this.$store.state.count;
},
stateA(){
return this.$store.state.stateA;
},
stateB(){
return this.$store.state.stateB;
}
}
這樣獲取共享狀態(tài)的數(shù)據(jù)也沒(méi)有什么問(wèn)題不過(guò)看起來(lái)還是有大量的重復(fù)冗余代碼,我們可以使用 mapState 輔助函數(shù)幫助我們生成計(jì)算屬性,讓你少按幾次鍵:
當(dāng)映射的計(jì)算屬性的名稱與 state 的子節(jié)點(diǎn)名稱相同時(shí),我們也可以給 mapState 傳一個(gè)字符串?dāng)?shù)組。
import {mapState} from 'vuex'
export default {
name: "index",
computed:{
...mapState(['count']),
}
}
小結(jié):使用 Vuex 并不意味著你需要將所有的狀態(tài)放入 Vuex。雖然將所有的狀態(tài)放到 Vuex 會(huì)使?fàn)顟B(tài)變化更顯式和易調(diào)試,但也會(huì)使代碼變得冗長(zhǎng)和不直觀。如果有些狀態(tài)嚴(yán)格屬于單個(gè)組件,最好還是作為組件的局部狀態(tài)。
4.2.getter
有的時(shí)候我們需要對(duì)共享狀態(tài)里面的某一個(gè)屬性做一些處理后再使用,我們可以把數(shù)據(jù)獲取后再在組件的計(jì)算屬性中處理,舉個(gè)例子如下:
// store/index.js
state: {
count:0,
numbers:[0,1,2,3,4,5,6,7,8]
},
// Index組件
<template>
<div class="index">
{{count}}
<br>
{{numbers.join()}}
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "index",
computed:{
...mapState(['count']),
numbers(){
return this.$store.state.numbers.filter((item)=>{
return item>3;
})
}
}
}
</script>
結(jié)果如下:

那么問(wèn)題來(lái)了,如果多個(gè)組件都要做同樣的處理,我們就需要把一份代碼復(fù)制到多個(gè)地方,顯然是不大合理的,于是有了getter,可以理解為組件里面的計(jì)算屬性。示例如下:
/ store/index.js
getters: {
filterNumbers(state){
return state.numbers.filter((item)=>{
return item>3;
})
}
},
// Index組件
<template>
<div class="index">
{{count}}
<br>
{{filterNumbers.join()}}
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "index",
computed:{
...mapState(['count']),
filterNumbers(){
return this.$store.getters.filterNumbers;
}
}
}
</script>
結(jié)果完全一樣,我們可以根據(jù)this.$store.getters.屬性名來(lái)獲取getters,也可以通過(guò) mapGetters 輔助函數(shù)將 store 中的 getter 映射到局部計(jì)算屬性:
具體實(shí)現(xiàn)方式如下:
<template>
<div class="index">
{{count}}
<br>
{{filterNumbers.join()}}
<br>
{{antherNumbers.join()}}
</div>
</template>
<script>
import {mapState,mapGetters} from 'vuex'
export default {
name: "index",
computed:{
...mapState(['count']),6
...mapGetters(['filterNumbers']),
...mapGetters({
antherNumbers:'filterNumbers'
})
}
}
</script>
如果用同一名字直接把數(shù)組作為參數(shù),如果想改一個(gè)名字,可以傳入一個(gè)對(duì)象作為參數(shù),結(jié)果如下:

4.3.mutation
在組件內(nèi),來(lái)自store的數(shù)據(jù)只能讀取,不能手動(dòng)改變,改變store中數(shù)據(jù)唯一的途徑就是顯示的提交mutations。Vuex 中的 mutation 非常類似于事件:每個(gè) mutation 都有一個(gè)字符串的 事件類型 (type) 和 一個(gè) 回調(diào)函數(shù) (handler)。這個(gè)回調(diào)函數(shù)就是我們實(shí)際進(jìn)行狀態(tài)更改的地方,并且它會(huì)接受 state 作為第一個(gè)參數(shù)。改變代碼如下:
// store/index.js
mutations: {
add(state){
state.count++;
}
},
// Index組件
**
<button @click="add">+</button>
**
methods:{
add(){
this.$store.commit('add');
console.log(this.count);
}
**

連續(xù)點(diǎn)擊5次增加按鈕,發(fā)現(xiàn)count的值也改變了。當(dāng)然,我們也可以傳參進(jìn)去
// store/index.js
mutations: {
add(state,n){
state.count+=n;
}
},
// Index組件
**
<button @click="add">+</button>
**
methods:{
add(){
this.$store.commit('add',10);
console.log(this.count);
}
**
觸發(fā)方法語(yǔ)句為:this.$store.commit(方法名);也可以使用輔助函數(shù)mapMutations代替:
methods:{
...mapMutations(['add']),
}
4.4.action
前面我們講過(guò),mutation有必須同步執(zhí)行這個(gè)限制,我們?cè)跇I(yè)務(wù)需求中有時(shí)候需要在獲取ajax請(qǐng)求數(shù)據(jù)之后再操作或定時(shí)器操作數(shù)據(jù),這些都屬于異步請(qǐng)求,要用actions來(lái)實(shí)現(xiàn)。具體實(shí)現(xiàn)如下:
// store/index.js
mutations: {
changeCount(state){
state.count=3000;
},
},
actions: {
changeCount3000s(context){
setTimeout(()=>{
context.commit('changeCount')
},3000)
// Index組件
<button @click="changeCount3000s">點(diǎn)擊按鈕3s后count的值改變</button>
methods:{
...mapMutations(['add']),
changeCount3000s(){
this.$store.dispatch('changeCount3000s');
}
}
我們?cè)邳c(diǎn)擊按鈕3s后count的值改變?yōu)?000,我們可以通過(guò)this.$store.dispatch(方法名)來(lái)觸發(fā)事件,也可以通過(guò)輔助函數(shù)mapActions來(lái)觸發(fā)。
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
methods:{
...mapMutations(['add']),
...mapActions(['changeCount3000s'])
}
學(xué)會(huì)以上幾個(gè)屬性的使用基本就可以滿足平時(shí)業(yè)務(wù)中的需求了,但使用Vuex會(huì)有一定的門(mén)檻和復(fù)雜性,它的主要使用場(chǎng)景是大型單頁(yè)面應(yīng)用,如果你的項(xiàng)目不是很復(fù)雜,用一個(gè)bus也可以實(shí)現(xiàn)數(shù)據(jù)的共享,但是它在數(shù)據(jù)管理,維護(hù),還只是一個(gè)簡(jiǎn)單的組件,而Vuex可以更優(yōu)雅高效地完成狀態(tài)管理,所以,是否使用Vuex取決于你的團(tuán)隊(duì)和技術(shù)儲(chǔ)備。
參考資料:
《Vue.js實(shí)踐》 Vuex
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求
這篇文章主要介紹了Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06
Vue新手指南之創(chuàng)建第一個(gè)vue-cli腳手架程序
vue-cli 是一個(gè)官方發(fā)布 vue.js 項(xiàng)目腳手架,使用 vue-cli 可以快速創(chuàng)建 vue 項(xiàng)目。這篇文章主要給大家介紹了關(guān)于Vue新手指南之創(chuàng)建第一個(gè)vue-cli程序的相關(guān)資料,需要的朋友可以參考下2021-05-05
Vue實(shí)現(xiàn)Chrome小恐龍游戲的示例代碼
Google 給 Chrome 瀏覽器加了一個(gè)有趣的彩蛋,本文就詳細(xì)的介紹一下Vue實(shí)現(xiàn)Chrome小恐龍游戲的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下2022-04-04
vue keep-alive列表頁(yè)緩存 詳情頁(yè)返回上一頁(yè)不刷新,定位到之前位置
這篇文章主要介紹了vue keep-alive列表頁(yè)緩存 詳情頁(yè)返回上一頁(yè)不刷新,定位到之前位置,本文通過(guò)實(shí)例代碼效果圖展示給大家介紹的非常詳細(xì),需要的朋友可以參考下2019-11-11
vue-cli創(chuàng)建項(xiàng)目時(shí)由esLint校驗(yàn)導(dǎo)致報(bào)錯(cuò)或警告的問(wèn)題及解決
這篇文章主要介紹了vue-cli創(chuàng)建項(xiàng)目時(shí)由esLint校驗(yàn)導(dǎo)致報(bào)錯(cuò)或警告的問(wèn)題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-05-05
vue如何實(shí)現(xiàn)拖動(dòng)圖片進(jìn)行排序Vue.Draggable
這篇文章主要介紹了vue如何實(shí)現(xiàn)拖動(dòng)圖片進(jìn)行排序Vue.Draggable,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-04-04
antfu大佬的v-lazy-show教我學(xué)會(huì)了怎么編譯模板指令
這篇文章主要介紹了antfu大佬的v-lazy-show,我學(xué)會(huì)了怎么編譯模板指令示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04

