1.Vuex狀態
Vuex 是一個專爲 Vue.js 應用程序開發的狀態管理模式,其專門應對於多個組件共享一個狀態的情況。多個組件共享一個狀態時,可能需要進行狀態變更,然而兄弟組件間的狀態傳遞是做不到的,因此我們需要把這個共享的狀態抽離出來,以全局單例模式進行管理,這就是Vuex的作用。下面用一個簡單的示例來說明
先創建三個組件,每個組件都使用用戶的名字
A.Vue
<template>
<div id="A">
<p>A組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
export default {
name: "A",
data(){
return{
name:"小明"
}
}
}
</script>
<style scoped>
#A{
width:60%;
background-color: lightgreen;
color:white;
}
</style>
B.Vue
<template>
<div id="B">
<p>B組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
export default {
name: "B",
data(){
return{
name:"小明"
}
}
}
</script>
<style scoped>
#B{
width:70%;
background-color: lightskyblue;
color:greenyellow;
}
</style>
C.vue
<template>
<div id="C">
<p>C組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
export default {
name: "C",
data(){
return{
name:"小明"
}
}
}
</script>
<style scoped>
#C{
width:80%;
background-color: black;
color:white;
}
</style>
最後App.vue
<template>
<div id="app">
<A></A>
<B></B>
<C></C>
</div>
</template>
<script>
import A from "./components/A"
import B from "./components/B"
import C from "./components/C"
export default {
components:{
A,B,C
}
}
</script>
<style lang="less">
#app {
height:550px;
background: red;
width: 400px;
}
</style>
代碼比較簡單,最後的效果如下:
可以看到每個組件的用戶名字都叫小明,這時如果我們修改其中一個組件的用戶名字會 怎麼樣呢?比如修改A組件的用戶名字爲小華結果如下
可以看到小明的名字被改成了小華,但其他組件的名字並沒有被修改,因爲各組件之間的data是獨立的,私有的,可是在我們實際應用中,用戶狀態是各組件共享的,如果一個組件修改了用戶狀態,各組件需要同時進行修改。
解決方法有兩種:第一種,你可以聲明用戶信息爲全局變量,這樣修改全局變量就可以,但這樣做無法進行有效地管理,Vue就提供了Vuex來進行狀態管理。
可以找到src/store/index.js,如下
我們可以把狀態存在state裏,拿上面的name舉例,如下存入name
import Vue from "vue";
import Vuex from "vuex";
Vue.use(Vuex);
export default new Vuex.Store({
state: {
name:"小華"
},
mutations: {},
actions: {},
modules: {}
});
然後各組件去取這個變量,通過this.$store.state.name
如A組件
<template>
<div id="A">
<p>A組件</p>
<p>名字:{{this.$store.state.name}}</p>
</div>
</template>
<script>
export default {
name: "A",
data(){
return{
name:"小華"
}
}
}
</script>
<style scoped>
#A{
width:60%;
background-color: lightgreen;
color:white;
}
</style>
其餘組件一樣這樣改,最後效果如下:
所有名字都變成了小華,如果你修改了這個name,那所有組件都會跟着修改 ,
我們還可以這樣來取狀態,使用computed
<template>
<div id="C">
<p>C組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
export default {
name: "C",
computed:{
name(){
return this.$store.state.name;
}
}
}
</script>
<style scoped>
#C{
width:80%;
background-color: black;
color:white;
}
</style>
當一個組件需要獲取多個狀態時候,將這些狀態都聲明爲計算屬性會有些重複和冗餘。Vuex還提供一種更簡單的取值方法,使用mapState,拿A組件舉例,效果不變
<template>
<div id="A">
<p>A組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "A",
computed:mapState(['name'])
}
</script>
<style scoped>
#A{
width:60%;
background-color: lightgreen;
color:white;
}
</style>
或者,mapState裏傳一個對象,在B組件修改後如下,最後效果一樣
<template>
<div id="B">
<p>B組件</p>
<p>名字:{{name}}</p>
</div>
</template>
<script>
import {mapState} from 'vuex'
export default {
name: "B",
computed:mapState({
name: function (state) {
return state.name
}
})
}
</script>
<style scoped>
#B{
width:70%;
background-color: lightskyblue;
color:greenyellow;
}
</style>
這樣,我們就實現狀態的統一
2. Vuex getters
有時候組件共享狀態時並不是想獲取一個狀態下的所有數據,需要就那些過濾,一個做法時在組件裏用v-if去判斷,Vuex提供了getter進行過濾,假如我們有這些明星數據
stars: [
{ name: "劉德華", sex: "男" },
{ name: "周杰倫", sex: "男" },
{ name: "周迅", sex: "女" },
{ name: "baby", sex: "女" }
]
現在A組件要獲取全部明星數據,B組件要獲取男明星數據,C組件要獲取女明星數據,先寫A組件,使用v-for即可
A組件代碼如下:
<template>
<div id="A">
<p>A組件</p>
<p>全部明星</p>
<p v-for="star in stars" :key="star.name">
{{ star.name }}---{{ star.sex }}
</p>
</div>
</template>
<script>
import { mapState } from "vuex";
export default {
name: "A",
computed: mapState(["stars"])
};
</script>
<style scoped>
#A {
width: 60%;
background-color: lightgreen;
color: white;
}
</style>
效果如下所示:A組件顯示出了所有明星
B組件和C組件類似,想實現性別過濾,可以在getters上定義過濾規則
getters: {
boystars:state => state.stars.filter(star=>star.sex == "男"),
girlstars:state => state.stars.filter(star=>star.sex == "女")
},
然後在組件裏調用,如B組件代碼,C組件一樣,就不貼了
<template>
<div id="B">
<p>B組件</p>
<p>只要男明星</p>
<p v-for="star in boystars" :key="star.name">
{{ star.name }}---{{ star.sex }}
</p>
</div>
</template>
<script>
export default {
name: "B",
computed:{
boystars(){
return this.$store.getters.boystars;
}
}
};
</script>
<style scoped>
#B {
width: 70%;
background-color: lightskyblue;
color: greenyellow;
}
</style>
最後效果如下所示,實現了狀態的過濾
同樣地,與上面mapState類似,Vuex還提供mapGetters輔助函數,用法類似,如B組件可以寫成
<template>
<div id="B">
<p>B組件</p>
<p>只要男明星</p>
<p v-for="star in boystars" :key="star.name">
{{ star.name }}---{{ star.sex }}
</p>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "B",
computed: {
...mapGetters(["boystars"])
}
};
</script>
<style scoped>
#B {
width: 70%;
background-color: lightskyblue;
color: greenyellow;
}
</style>