Alex-Programer

Alex-Programer

随缘博客,不定期更新不确定的内容~
github
twitter

Vuex 基本使用

官方定義#

Vuex 是一個專為 Vue.js 應用程序開發的狀態管理模式。它採用集中式存儲管理應用的所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

注入 vuex#

import store from "./store";

new Vue({
  store,
});

store.js

import Vue from "vue";
import Vuex from "vuex";

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    msg: "hello world",
  },
  mutations: {},
  actions: {},
});

獲取狀態#

這樣在任何一個組件裡,都可以這樣獲取到這個 msg

<template>
  <div class="about">
    <h1>這是一個關於頁面</h1>
    <h2>{{$store.state.msg}}</h2>
  </div>
</template>

修改狀態#

mutations 提供一個修改狀態的方法

mutations: {
  setMsg(state, newMsg) {
    state.msg = newMsg
  }
}

再讓 actions 來提交修改的請求

actions: {
  setMsg ({ commit }) {
    commit('setMsg', 'hello')
  }
}

修改的動作,在其它組件裡去觸發

<template>
  <div class="about">
    <h1>這是一個關於頁面</h1>
    <h2>{{$store.state.msg}}</h2>
  </div>
</template>

<script>
export default {
  mounted () {
    this.$store.dispatch('setMsg')
  }
}
</script>

思考#

上例屬於簡單的狀態管理,state 在存放狀態、mutations 提供了修改狀態的方法、actions 負責觸發修改狀態的方法,並提交修改的數據;上例 actions 裡是手動修改的數據,工作中應該是提交請求的數據。但是上例中有個明顯的問題,誰都可以修改(dispatch)狀態。

命名空間#

如果項目足夠複雜,那麼可以使用 vuex 提供的命名空間來修改狀態。使用的前提還需要使用 vuexmodulesmodules是一個對象,其結構也是由statemutationsactions組成。區別是它多了一個namespaced 屬性,以此來使用命名空間。

修改狀態的三種方法#

dispatch#

先把原來寫的內容提取到一個 modules

store.js

import Vue from "vue";
import Vuex from "vuex";
import home from "./modules/home";

Vue.use(Vuex);

export default new Vuex.Store({
  modules: {
    home,
  },
});

./modules/home.js

export default {
  namespaced: true,
  state: {
    msg: "hello world",
  },
  actions: {
    setMsg({ commit }) {
      commit("setMsg", "hello");
    },
  },
  mutations: {
    setMsg(state, newMsg) {
      state.msg = newMsg;
    },
  },
};

最後取狀態和修改狀態

<template>
  <div class="about">
    <h1>這是一個關於頁面</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
export default {
  mounted () {
    this.$store.dispatch('home/setMsg')
  }
}
</script>

觀察最後修改時和之前的不同,無非是取狀態和修改狀態都多了一層 home ,提高了一定的使用門檻。儘管這樣,但至少可以識別操作的是哪個模塊的狀態。

上例再通過 modules 修改 狀態還有另一種等價的寫法

mapActions#

<template>
  <div class="about">
    <h1>這是一個關於頁面</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
import { mapActions } from 'vuex'

export default {
  methods: {
    ...mapActions('home', ['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

mapActions 執行完後返回的是一個對象,通過擴展運算法展開後,會在當前實例裡添加一個 setMsg 方法。調用這個方法就會觸發狀態的修改。

createNamespacedHelpers#

上面兩個方法都有一個很明顯的問題,如果在當前組件裡,需要修改的狀態有很多個。那麼就意味著有很多層 home。通過 vuexcreateNamespacedHelpers 方法,可以很友好的解決這個問題。

<template>
  <div class='about'>
    <h1>這是一個關於頁面</h1>
    <h2>{{$store.state.home.msg}}</h2>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions } = createNamespacedHelpers('home')

export default {
  methods: {
    ...mapActions(['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

簡化取值#

之前的例子一直沒有提到取值的問題,實際工作中也不推薦那麼去做;vuex 提供了一個 mapState 的方法,可以簡化取值。

<template>
  <div class='about'>
    <h1>這是一個關於頁面</h1>
    <h2>{{msg}}</h2>
  </div>
</template>

<script>
import { createNamespacedHelpers } from 'vuex'
const { mapActions, mapState } = createNamespacedHelpers('home')

export default {
  computed: {
    ...mapState(['msg'])
  },
  methods: {
    ...mapActions(['setMsg'])
  },
  mounted () {
    this.setMsg()
  }
}
</script>

提取變量#

回憶一下 setMsg 這個字眼出現的次數,在組件裡使用出現過,在 storemodules 裡出現過。這時提倡的做法,就是將這個 setMsg 提取出來,用一個常量保存;

./store/action-type.js

export const SET_MSG = "setMsg";

使用的時候,儘量避免直接使用 setMsg,這樣便於自己或其他人去維護。

總結#

vuex 的便利性不言而喻,根據項目的複雜度,它提供了漸進增強的方案。當項目很簡單時,不用 modules 就能解決基本需求。如果複雜度上升了,modules 自然是不二選擇。如果模塊的個數並不多,大可只用 dispatch。即便模塊多了起來,createNamespacedHelpers 也為後續工作鋪好了路。

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。