【16】vuex2.0 之 getter
有的組件中獲取到 store 中的state, 需要對進行加工才能使用,computed 屬性中就需要寫操作函數,如果有多個組件中都需要進行這個操作,那麽在各個組件中都寫相同的函數,那就非常麻煩,這時可以把這個相同的操作寫到store 中的getters, 每個組件只要引用getter 就可以了,非常方便。Getter 就是把組件中共有的對state 的操作進行了提取,它就相當於 對state 的computed. 所以它會獲得state 作為第一個參數。
假設我們在點擊increment按鈕的時候,再增加一個額外的數,那麽就需要在display.vue 中顯示我們多增加了哪個數,同時在increment.vue 中要獲得這個數進行相加。state 狀態中增加 anotherIncrement: 5.要獲取到state 中的這個值, 在每個組件中都要寫computed: this.$store.state. countAnother, 這時就可以用getters, 然後在每個組件中computed 中使用getter.
display.vue 修改如下:
<template> <div> <h3>Count is {{count}}</h3> <h3>AnoterIncrement is {{countAnother}}</h3> </div> </template> <script> import {mapState} from "vuex"; export default { computed: { ...mapState(["count"]), countAnother: function () { // 獲取state return this.$store.getters.countAnother; } } } </script>
increment.vue 修改如下,這裏dispatch中,只能接受一個參數,如果我們要傳多個參數的話,需要把所有的參數組裝成對象。
<script> import {mapActions} from "vuex"; export default { data() { return { incrementValue: 0 } }, computed: { show: function() { return this.$store.state.waiting; }, countAnother: function () { // 獲取getters return this.$store.getters.countAnother; } }, methods: { ...mapActions(["increment","decrement"]), incrementWithValue() {
// dispatch 只能接受一個參數,需要傳對象參數 this.$store.dispatch("incrementWithValue", { value:this.incrementValue, anotherValue: this.countAnother}) } } } </script>
store.js 修改如下:
const store = new Vuex.Store({ state: { count:0, // 新增waiting 狀態 waiting: false, // 額外需要增加的數字 anotherIncrement: 5 }, mutations: { // 加1 INCREMENT(state) { state.count++; }, // 減1 DECREMENT(state) { state.count-- }, INCREMENT_WITH_VALUE(state, value){ state.count = state.count + value.intValue + value.anotherValue; }, // 顯示和隱藏waiting SHOW_WAITING_MESSAGE(state){ state.waiting = true; }, HIDE_WAITING_MESSAGE(state){ state.waiting = false; } }, actions: { increment({commit}){ commit("INCREMENT") }, decrement({commit}){ commit("DECREMENT") }, incrementWithValue({commit}, value){ commit("SHOW_WAITING_MESSAGE"); let intValue = parseInt(value.value) let anotherValue = value.anotherValue setTimeout(function() { if(isNaN(intValue)) { alert("Not an Interger") }else { commit("HIDE_WAITING_MESSAGE"); commit("INCREMENT_WITH_VALUE", {intValue, anotherValue}) } }, 2000) } }, getters: { // getters countAnother: function (state) { return state.anotherIncrement } } })
vuex 也提供了mapGetters 方法,和其的mapState,mapActions 是一樣的,如果組件中使用的getters 和store 裏面的getters 相同,那就用 數組形式,如果不相同,那就要用對象形式。
increment.vue 修改一下:
computed: { show: function() { return this.$store.state.waiting; }, ...mapGetters{["countAnother"]}
},
到這裏,vuex 中的 state, action,mutation, getter 等重要概念就介紹完了,但是,我們把所有的getters, actions, mutations 都寫到的store 中,如果有很多的話,代碼可讀性太差,所以就需要 action 創建一個actions.js 文件,mutations 創建一個mutation.js文件,getters 也創建一個getters.js文件,state 作為主要的入口文件命名為index.js,把這四個js文件放到store 文件夾中。
state所在的文件命名為index.js 還和 nodejs 加載模塊有關。如果不命名為index.js , 那假設命名為store.js.
在store.js, 我們暴露出通過 new Vuex.Store 構造函數生成的store 對象(export default new Vuex.Store({...})), 這個store 對象需要在 main.js 中引入,然後註入到vue 根實例中。所以在 main.js 中需要寫入 import store from ‘./store/store.js‘, 後面的路徑就比較長了。如果我們命名為 index.js, 我們可以直接寫 import store from ‘./store‘, 後面的路徑直接到文件夾名就可以了,index.js 可以省略。node 在加載文件夾模塊的時候,有如下規定:
var mode = require(“./moduleDir”);
如果moduleDir 是一個文件夾名,Node 就會在指定的文件夾下查找模塊。Node 會假定該文件夾是一個包,並試驗查找包定義。 包定義在名為 package.json 文件中。如果文件夾中沒有package.json, 那麽就會查找index.js文件,相當於加載 var mode = require(“./moduleDir/index.js”). 如果有package.json 文件,就會查找文件中的 main屬性,如下package.json文件, 相當於加載 var mode = require(“./moduleDir/lib/mymodldule.js”)
{ “name”: “myModule”, “main” : “./lib/myModule.js”}
在src 目錄下,新建store.js 文件夾,裏面新建getters.js, actions.js, mutations.js, index.js 文件。
getters.js 文件如下:
export default { countAnother: function (state) { return state.anotherIncrement } }
actions.js 文件如下:
export default { increment({commit}){ commit("INCREMENT") }, decrement({commit}){ commit("DECREMENT") }, incrementWithValue({commit}, value){ commit("SHOW_WAITING_MESSAGE"); let intValue = parseInt(value.value) let anotherValue = value.anotherValue setTimeout(function() { if(isNaN(intValue)) { alert("Not an Interger") }else { commit("HIDE_WAITING_MESSAGE"); commit("INCREMENT_WITH_VALUE", {intValue, anotherValue}) } }, 2000) } }
muations 文件如下:
export default { // 加1 INCREMENT(state) { state.count++; }, // 減1 DECREMENT(state) { state.count-- }, INCREMENT_WITH_VALUE(state, value){ state.count = state.count + value.intValue + value.anotherValue; }, // 顯示和隱藏waiting SHOW_WAITING_MESSAGE(state){ state.waiting = true; }, HIDE_WAITING_MESSAGE(state){ state.waiting = false; } }
index.js 文件如下:
import Vue from "vue"; import Vuex from "vuex"; Vue.use(Vuex); // 引入actions, mutations, getters import actions from "./actions.js" import mutations from "./mutations.js" import getters from "./getters.js" const state = { count:0, // 新增waiting 狀態 waiting: false, // 額外需要增加的數字 anotherIncrement: 5 } export default new Vuex.Store({ state, mutations, actions, getters })
【16】vuex2.0 之 getter