MENU

Vuex使用笔记

July 8, 2022 • vue

部署

工程目录下创建./store/index.js

//vuex store
//引入 Vuex , Vue
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);
//准备 actions 用于响应组件中的动作
const actions = {};
//用于操作数据(state)
const mutations = {};
//用于存储数据
const state = {};
//创建 store 并暴露
export default new Vuex.Store({
  actions,
  mutations,
  state,
});

在 main.js 中配置

import Vue from "vue";
import App from "./App.vue";
import Vuex from "vuex";
import store from "./store/index.js";

Vue.config.productionTip = false;

Vue.use(Vuex);

new Vue({
  render: (h) => h(App),
  store,
}).$mount("#app");

使用

结构示意

vuex

各部分解释

  • Actions 用于数据处理加工,然后 commit 到 multations 处理
  • Mutations 与开发者工具相连,可在开发者工具中查看调试
  • State 存储数据,可以理解为能动态响应的全局变量,各组件中都可获取

Actions 中相关

jiaJ(context, value) {
    //console.log(context, value);
    if (context.state.sum % 2) context.commit("JIA", value);
    else context.dispatch("else",value)
  },
else(context,value){...}

可接受两个参数,本别是 context 上下文和 value 数值,context 中有 dispatch,commit,state 等,如果逻辑代码较长,需要分布处理,可以使用 dispatch 递交给下一个逻辑处理函数,当所有处理函数处理完毕时,就可以使用 commit 提交到数据处理模块。当前状态下可以获取 state 中的变量并判断,但最好不要在这修改。

Mutations 相关

const mutations = {
  JIA(state, value) {
    state.sum += value;
  },
  JIAN(state, value) {
    state.sum -= value;
  },
};

纯纯的操作数据阶段,可获取两个参数 state,value,如果已知无逻辑判断,可以在组件中直接 commit 到这里,跳过 Actions 环节。Mutation 中的函数要大写以区分 Actions 中的函数

组件模板中

<template>
  <div>
    <h1> 当前求和为:{{ $store.state.sum }}</h1>
    <select name="sel" id="sel" v-model.number="n">
      <option value="1">1</option>
      <option value="2">2</option>
      <option value="3">3</option>
    </select>
    <button @click="add">+</button>
    <button @click="minus">-</button>
    <button @click="addOnlyJ"> 当前求和为奇数再加 </button>
    <button @click="addWait"> 等一等再加 </button>
  </div>
</template>

<script>
export default {
  name: "A-count",
  data() {
    return {
      n: 1,
    };
  },
  methods: {
    add() {
      this.$store.commit("JIA", this.n);
    },
    minus() {
      this.$store.commit("JIAN", this.n);
    },
    addOnlyJ() {
      this.$store.dispatch("jiaJ", this.n);
    },
    addWait() {
      this.$store.dispatch("jiaW", this.n);
    },
  },
};
</script>

<style>
</style>
  • 模板中,使用{{$store.state.xxx}}获取变量
  • 方法中,需要逻辑判断处理的,用 this.$store.disptch 交给 Actions 处理
  • 不需要逻辑判断的,可以直接 this.$store.commit 交给 Mutations 处理

getters 配置项

配置

//getters 用于 state 中已有数据加工,返回新的数据,类似于 computed,优点是组件可复用
const getters = {
  bigSum(state) {
    return state.sum * 10;
  },
};
//创建 store 并暴露
export default new Vuex.Store({
  actions,
  mutations,
  state,
  getters,
});

使用

<h1>getters.bigSum = {{ $store.getters.bigSum }}</h1>

mapState 与 mapGetters

引用原因

模板中重复出现 $store.state$state.getters 导致模板不够简洁,所以需要用其他变量代替这个长表达式,例如 computed:

SUM(){return this.$store.state.sum;}
...more

但是变量太多又造成 computed 冗余,于是 mapState 和 mapGetters 出现了

使用

import { mapGetters, mapState } from "vuex";

...

computed: {
    ...mapState({ SUM: "sum", DATA: "data" }),
    ...mapGetters({ BIGSUM: "bigSum" }),
  },
mapState 和 mapGetters 使用时提交对象,key 是新的变量名,value 是在 state 或者 getters 中的变量名,返回一个 Object:{ key : function },这样就与 computed 对应上了,key 就是那个计算属性名,function 就是计算函数,所以使用扩展运算符即可使用

简单表达

key 与 value 相同,可以直接用数组作为提交参数

mapState(['sum','data'])

mapMutations 与 mapActions

methods: {
    // add() {
    //   this.$store.commit("JIA", this.n);
    // },
    // minus() {
    //   this.$store.commit("JIAN", this.n);
    // },
    ...mapMutations({ add: "JIA", minus: "JIAN" }),
    // addOnlyJ() {
    //   this.$store.dispatch("jiaJ", this.n);
    // },
    // addWait() {
    //   this.$store.dispatch("jiaW", this.n);
    // },
    ...mapActions({ addOnlyJ: "jiaJ", addWait: "jiaW" }),
  },

跟上面的 map 方法类似,可用数组形式简写,需要注意的是需要在模板@click 事件中传入参数

<button @click="add(n)">+</button>
    <button @click="minus(n)">-</button>
    <button @click="addOnlyJ(n)"> 当前求和为奇数再加 </button>
    <button @click="addWait(n)"> 等一等再加 </button>

模块化 namespace

//vuex store
//引入 Vuex , Vue
import Vuex from "vuex";
import Vue from "vue";
Vue.use(Vuex);

const addOptions = {
  namespaced:true,
  actions: {
    jiaJ(context, value) {
      //console.log(context, value);
      if (context.state.sum % 2) context.commit("JIA", value);
    },
    jiaW(context, value) {
      setTimeout(() => {
        context.commit("JIA", value);
      }, 500);
    },
  },
  mutations: {
    JIA(state, value) {
      state.sum += value;
    },
    JIAN(state, value) {
      state.sum -= value;
    },
  },
  state: {
    sum: 0,
    data: "HEllO",
  },
  getters: {
    bigSum(state) {
      return state.sum * 10;
    },
  },
};

//创建 store 并暴露
export default new Vuex.Store({
  modules:{
    addAbout:addOptions,
  }
});

将 store/index.js 中的代码模块化拆分,方法如下

  1. 配置拆分对象
  2. namespaced 需要设置为 true
  3. 暴露时使用 modules
  4. 使用时在 map 类方法中加入一个命名空间参数
computed: {
    ...mapState("addAbout", { SUM: "sum", DATA: "data" }),
    ...mapGetters("addAbout", { BIGSUM: "bigSum" }),
  },
  methods: {
    ...mapMutations("addAbout", { add: "JIA", minus: "JIAN" }),
    ...mapActions("addAbout", { addOnlyJ: "jiaJ", addWait: "jiaW" }),
  },

注意:模块化分类后

  1. 组件中使用 state 变量表达为 this.$store.state.分类名.变量名
  2. 组件中使用 getters 变量表达为 this.$store.getters[分类名/变量名]
  3. 组件中使用 commit/dispatchthis.$store.commit/dispatch('分类名/变量名',value)