有的组件中获取到 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 })