入坑原因很简单,就是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请各路大神放心指教