vue學習(3)Vuex探索(上)

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>

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章