从0开始创建vue3.0+vite+ts之vuex(三)

257 阅读1分钟

之前写了基础创建和组件间交互
从0开始创建vue3.0+vite+ts(一)
从0开始创建vue3.0+vite+ts之组件间传参(二)
今天讲讲 状态管理模式 vuex的使用

  1. vuex在vue3.0+使用

vuex在vue3.0+使用

// 引用vuex
npm install vuex --save
或
yarn add vuex --save

新建文件 store.ts

import { createStore } from "vuex"; // 创建一个新的 store 实例
export const store = createStore<object>({
  state: {
    msg: "这是默认store数据",
  },
  getters: {
    getMsg: (state) => state.msg,
  },
  mutations: {
    setMsg(state: object, msg: string) {
      state.msg = msg;
    },
  },
  actions: {
    setMsg({ state, dispatch, commit }, msg: string) {
      state.msg = msg;
    },
  },
});

方法一:直接引用store

index.vue 应用 store

<template> 
    <div> 
      <el-button @click="onCommit">commit</el-button>
      <el-button type="primary" @click="onDispatch">dispatch</el-button>
      msg = {{ msg }}; msg2 = {{ msg2 }}
    </div> 
</template> 
<script setup lang="ts"> 
import { computed } from 'vue'
import { store } from '@/store'

const msg = computed(() => store.state.msg)
const msg2 = computed(() => store.getters.getMsg)

function onCommit(v) {
  store.commit('setMsg', '同步操作')
}
function onDispatch(v) {
  store.dispatch('setMsg', '异步操作')
}
</script>

方法二:使用辅助函数mapActions, mapMutations, mapGetters, mapState

在 index.vue 应用辅助函数 mapActions, mapMutations, mapGetters, mapState 直接使用如下

<template> 
    <div> 
      <el-button @click="onCommit">commit</el-button>
      <el-button type="primary" @click="onDispatch">dispatch</el-button>
      msg = {{ msg }}; msg2 = {{ msg2 }}
    </div> 
</template> 
<script setup lang="ts"> 
import { computed } from 'vue'
import { mapActions, mapMutations, mapGetters, mapState } from 'vuex'
import { store } from '@/store'
const storeState = mapState(['msg'])
const storeGetters = mapGetters(['getMsg'])
const storeMutations = mapMutations(['setMsg'])
const storeActions = mapActions(['setMsg'])

const msg = computed(storeState.msg.bind({ $store: store }))
const msg2 = computed(storeGetters.getMsg.bind({ $store: store }))

function onCommit(v) {
  storeMutations.setMsg.bind({ $store: store })('同步操作')
}
function onDispatch(v) {
  storeActions.setMsg.bind({ $store: store })('异步操作')
}
</script>

看这有点复杂,优化一下,抽离封装 useStore.ts,并引入 useStore.ts
实现如下

import { computed } from "vue";
import { mapActions, mapMutations, mapGetters, mapState } from "vuex";
import { store } from "@/store";
export const useState = function (v: Array<string> | object) {
  const data: object = {};
  const state: object = mapState(v);
  Object.keys(state).forEach((key) => {
    data[key] = computed(state[key].bind({ $store: store }));
  });
  return data;
};
export const useGetters = function (v: Array<string> | object) {
  const data: object = {};
  const getters: object = mapGetters(v);
  Object.keys(getters).forEach((key) => {
    data[key] = computed(getters[key].bind({ $store: store }));
  });
  return data;
};
export const useMutations = function (v: Array<string> | object) {
  const data: object = {};
  const mutations: object = mapMutations(v);
  Object.keys(mutations).forEach((key) => {
    data[key] = mutations[key].bind({ $store: store });
  });
  return data;
};
export const useActions = function (v: Array<string> | object) {
  const data: object = {};
  const actions: object = mapActions(v);
  Object.keys(actions).forEach((key) => {
    data[key] = actions[key].bind({ $store: store });
  });
  return data;
};

上述还有优化空间,进一步优化 useStore.ts

import { computed } from "vue";
import { mapActions, mapMutations, mapGetters, mapState } from "vuex";
import { store } from "@/store";
function fn(v: Array<string> | object, m: object, type?: string) {
  const data: object = {};
  const fun: object = m(v);
  Object.keys(fun).forEach((key) => {
    if (type && (type === "state" || type === "getter")) {
      data[key] = computed(fun[key].bind({ $store: store }));
    } else {
      data[key] = fun[key].bind({ $store: store });
    }
  });
  return data;
}
export const useState = (v: Array<string> | object) => fn(v, mapState, "state");
export const useGetters = (v: Array<string> | object) => fn(v, mapGetters, "getter");
export const useMutations = (v: Array<string> | object) => fn(v, mapMutations);
export const useActions = (v: Array<string> | object) => fn(v, mapActions);

index.vue 应用看看效果

<template> 
    <div> 
      <el-button @click="onCommit">commit</el-button>
      <el-button type="primary" @click="onDispatch">dispatch</el-button>
      msg = {{ msg }}; msg2 = {{ msg2 }}
    </div> 
</template> 
<script setup lang="ts"> 
import { useState, useGetters, useMutations, useActions } from '@/store/useStore'
const state = useState(['msg'])
const getters = useGetters(['getMsg'])
const mutations = useMutations(['setMsg'])
const actions = useActions(['setMsg'])

const msg: string = state.msg
const msg2: string = getters.getMsg

function onCommit(v) {
  mutations.setMsg('同步操作')
}
function onDispatch(v) {
  actions.setMsg('异步操作')
}
</script>

image.png
完美!!!就这样vuex你已经学会使用了