Vue-認識狀態管理vuex


  vuex是一個專門為vue.js設計的狀態管理模式,並且也可以使用devtools進行調試,可以多個組件共享狀態。簡單來說,就是共享的狀態用state來存放,用mutations來操作state,但是需要用store.commit來主動式的操作mutations。

vuex

  用一個簡單的demo來認識vuex。

1520926961(1)

  注意在使用vuex之前要先安裝依賴(前提是已經用Vue腳手架工具構建好項目)

cnpm install vuex –save

  在入口文件main.js里需要引入vuex、注冊vuex、實例化store、把store放在全局的實例化對象里。

import Vue from 'vue'
import App from './App'
//1.引入vuex
import Vuex from 'vuex'
import Apple from './components/Apple'
import Banana from './components/Banana'
Vue.config.productionTip = false
//2.注冊
Vue.use(Vuex);
//3.實例化store
let store=new Vuex.Store({
    state:{
        totalPrice:0
    },
    mutations:{
        increment(state,price){
            state.totalPrice+=price
        },
        decrement(state,price){
            state.totalPrice-=price
        }
    },
    actions:{
        increase (context,price){
            context.commit('increment',price)
        },
        decrease (context,price){
            context.commit('decrement',price)
        }
    },
    getters:{
        discount(state){
            return state.totalPrice *0.8;
        }
    }
})
new Vue({
  el: '#app',
  //4.把store放在全局的實例化對象里,可以在全局的所有地方用
  store,
  components: { App},
  template: '<App/>'
})

  實例化store時,用到了state,mutations,actions,getters參數,下面來單獨介紹 它們:

state
  vuex使用單一狀態樹,那么就可以用一個對象來包含全部的應用層級狀態。所以state就作為數據源。

mutations
  更改 Vuex 的 store 中的狀態的唯一方法是提交 mutation。Vuex 中的 mutation 非常類似於事件:每個 mutation 都有一個字符串的 事件類型 (type) 和 一個 回調函數 (handler)。這個回調函數就是我們實際進行狀態更改的地方,並且它會接受 state 作為第一個參數。不能直接調用一個 mutation handler,這個選項更像是事件注冊:“當觸發一個type為 increment的 mutation 時,調用此handler。”要喚醒一個 mutation handler,需要調用 store.commit 方法觸發相應的 type 。可以向store.commit傳入額外的參數這個參數就叫做mutations的載荷。 在更多的情況下,載荷應該是一個對象。這樣可以包含更多的字段。

  mutations必須是同步函數。那我們如何來異步的更新state呢?答案是actions。

actions
  actions類似於 mutations 不同的是:
  actions 提交的是mutations,而不是直接變更狀態,這也就形成了 actions —— mutations —— state 的過程。
  actions 可以包含任意異步操作。
  action 函數接受一個與 store 實例具有相同方法和屬性的 context 對象,因此你可以調用context.commit提交一個 mutation,或者通過context.state和context.getters來獲取 state 和 getters。但是如何觸發呢?答案: store.dispatch
getters

  有時候我們需要從 store 中的 state 中派生出一些狀態,getter 會暴露為 store.getters 對象在組件中使用。

modules

        除了上邊用到的4個參數,store還有另一個參數:modules。
  vuex允許把store進行一個功能拆分,分割成不同的模塊(module)。每個模塊都擁有自己的store,mutations,action,getters。

App.vue

<template>
  <div id="app">
    <Apple></Apple>
    <Banana></Banana>
    <p> 總價{{totalPrice}}</p>
    <p> 折后價:{{discountPrice}}</p>
  </div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
import Apple from './components/Apple'
import Banana from './components/Banana'
export default {
  name: 'App',
  components: {
    HelloWorld,
    Apple,
    Banana
  },
  computed:{
    totalPrice(){
    //由於vuex的狀態存儲是響應式的,所以從store實例中讀取狀態的最簡單方法就是使用計算屬性來返回某個狀態:
      return this.$store.state.totalPrice
    },
    discountPrice(){
    //getter 會暴露為 store.getters 對象
      return this.$store.getters.discount    
      }
  }
}
</script>

  由於vuex的狀態存儲是響應式的,所以從store實例中讀取狀態的最簡單方法就是使用計算屬性來返回某個狀態:store.state.totalPrice

  getters 會暴露為 store.getters 對象:用store.getters.discount可以獲取到getter里discount對state計算后的結果

  當一個組件需要獲取多個狀態時候,將這些狀態都聲明為計算屬性會有些重復和冗余。為了解決這個問題,我們可以使用 mapState 輔助函數幫助我們生成計算屬性。

 
         
import { mapState } from 'vuex'
computed: {
    ...mapState(['totalPrice'])
        
    ...
 
  }

Banana.vue

<template>
<div>
        <p>{{msg}} 單價{{price}}</p>    
        <button @click="addOne">add one</button>
        <button @click="minusOne">minus one</button>
</div>
</template>
<script>
export default{
    data(){
        return{
            msg:'banana',
            price:15
        }
    },
    methods:{
        addOne(){
            //直接commit一個mutation
            this.$store.commit('increment',this.price)
        },
        minusOne(){
            this.$store.commit('decrement',this.price)
        }
    }
}
</script>

addOne()函數里調用 store.commit 方法觸發 type為"increment"的mutation;minusOne()函數里調用 store.commit 方法觸發 type為"decrement"的mutation。

  可以在組件中使用 this.$store.commit('xxx') 提交 mutation,或者使用 mapMutations 輔助函數將組件中的 methods 映射為 store.commit 調用。

methods:{
      addOne(){
          this.increment(this.price)
      },
      minusOne(){
          this.decrement(this.price)
      },
      ...mapMutations(['increment', 'decrement'])
}

Apple.vue

<template>
<div>
    <p> {{msg}}單價:{{price}} </p>    
    <button @click="addOne">add one</button>
    <button @click="minusOne">minus one</button>
</div>
</template>
<script>
export default{
    data(){
        return{
            msg:'apple',
            price:5
        }
    },
    methods:{
        addOne(){
            //dispatch一個action,以action作為一個中介再去commit一個mutation
            this.$store.dispatch('increase',this.price)
        },
        minusOne(){
            this.$store.dispatch('decrease',this.price)
        }
    }
}
</script>

  addOne()函數里調用 store.dispatch方法觸發名為"increase"的action,對應的,在increase這個action里再去調用 context.commit方法觸發 type為"increment"的mutation;minusOne()函數里調用 store.dispatch方法觸發名為"decrease"的action,對應的,在decrease這個action里再去調用context.commit方法觸發 type為"decrement"的mutation。action相當於中介。

mutations和actions的區別與聯系:

action只能調用mutation不能直接更改state,執行 action 來分發 (dispatch) 事件通知 store 去改變。
action里可以進行一些異步的操作,再去觸發mutation 。
mutation里必須是同步的觸發操作state。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM