入坑【vue3你可能不需要vuex系列】:Vue3+Typescript

207 阅读1分钟

入坑原因很简单,就是vuex的typescript感觉有点难写,然后冲浪看到几篇【vue3的vuex替代方案】的文章,然后就……虽然写这篇文章的时候项目还没写完,不过已经遇见一些“后遗症”了,比如一些和vuex相关的第三方插件的使用……等我写完项目了再更新吧……(20220107)

项目src目录结构

|--- mixins
|------store.ts
|--- store
|------index.ts
|------component.ts
|----App.vue
|----main.ts

vue文件使用

<template>
  <span>{{getter.component.curComponentId.value}}</span>
  <a
    href="javascript:;"
    @click="commit.component.updateCurComponentIndex(0)"
  >{{store.component.curComponentIndex}}</a>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import Store from "@/mixins/store";
export default defineComponent({
  setup() {
    const { store, getter, commit } = Store();
    
    // store.component.curComponentIndex
    // getter.component.curComponentId.value
    // commit.component.updateCurComponentIndex(0)
        
    
    return { store, getter, commit };
  },
});
</script>

Store文件书写

index.ts
相当于做一个集合单例

import {componentState, componentCommit, componentGetter} from "@/store/component";
import { reactive, readonly } from "@vue/reactivity";

const createStore = (): StoreObj => {
  const store = reactive<State>({
    component: componentState,
  });

  const commit: Commit = {
    component: componentCommit(store.component),
  };

  const getter: Getter = {
    component: componentGetter(store.component),
  };

  return { commit: readonly(commit), store: readonly(store), getter: readonly(getter) };
};

const store = createStore();

export default store;

相关interface

import {componentStateInterface, componentCommitInterface, componentGetterInterface} from "@/store/component";

export interface StoreObj {
  store: State;
  commit: Commit;
  getter: Getter;
}

export interface State {
  component: componentStateInterface;
}

export interface Commit {
  component: componentCommitInterface;
}

export interface Getter {
  component: componentGetterInterface;
}

component.ts
相当于模块化了,可以搞多个,如果需要其他模块的state应该可以在index.ts那里传入,这次我把公共的放index里面了

// state
export const componentState: componentStateInterface = {
  curComponentIndex: -1,
};

// commit
export const componentCommit = (state: componentStateInterface): componentCommitInterface => {
  return {
    updateCurComponentIndex(index) {
      state.curComponentIndex = index;
    }
  };
};

// getter
export const componentGetter = (state: componentStateInterface): componentGetterInterface => {
  let getterObj = {
    curComponentId: computed(() => {
      return `id-${state.curComponentIndex}`;
    }),
  };
  return getterObj;
};

相关interface

export interface componentStateInterface {
  curComponentIndex: number;
}

export interface componentGetterInterface {
  curComponentId: ComputedRef<string>;
}

export interface componentCommitInterface {
  updateCurComponentIndex(x: number): void;
}

store全局挂载

main.ts

import { createApp } from "vue";
import App from "./App.vue";
import store from "@/store/index.ts";

const app = createApp(App);
app.config.globalProperties.$store = store;

app.mount("#app");

注入

App.vue

<script lang="ts">
import { defineComponent, provide } from "vue";
import { getCurrentInstance } from "vue";

export default defineComponent({
  name: "App",
  setup() {
    const store = getCurrentInstance()?.appContext.config.globalProperties
      .$store;
    provide("store", store.store);
    provide("commit", store.commit);
    provide("getter", store.getter);
  },
});
</script>

抽取方法

mixins/store.ts

import { getCurrentInstance, inject } from "vue";
import { StoreObj } from "@/store/index";

export default (): StoreObj => {
  const defaultStore = getCurrentInstance()?.appContext.config.globalProperties.$store;
  const store = inject("store", defaultStore.store);
  const getter = inject("getter", defaultStore.getter);
  const commit = inject("commit", defaultStore.commit);
  return {
    store,
    getter,
    commit,
  };
};

这里其实也可以不抽出来,直接在对应的vue里面inject也是ok的,抽是为了少写几行inject……

写在最后:代码有删减(可能会改漏),然后有bug请各路大神放心指教