TypeScript在Vuex4中使用TS實(shí)戰(zhàn)分享
簡介
雖然TypeScript知識(shí)點(diǎn)學(xué)了很多,但是在實(shí)際項(xiàng)目中很多小伙伴還并不知道怎么用,今天筆者結(jié)合Vuex4來使用TypeScript實(shí)戰(zhàn)一下。
本文分vuex4類型 Api分析和vuex4實(shí)戰(zhàn)兩部分講述。
首先我們來分析下 vuex4 的類型 Api
createStore
我們可以先看看createStore方法,發(fā)現(xiàn)它需要傳遞一個(gè)泛型,并且這個(gè)泛型會(huì)應(yīng)用到state上。
export function createStore<S>(options: StoreOptions<S>): Store<S>;
export interface StoreOptions<S> {
state?: S | (() => S);
getters?: GetterTree<S, S>;
actions?: ActionTree<S, S>;
mutations?: MutationTree<S>;
modules?: ModuleTree<S>;
plugins?: Plugin<S>[];
strict?: boolean;
devtools?: boolean;
}GetterTree
我們可以看到getters的類型GetterTree接收了兩個(gè)泛型。
export interface GetterTree<S, R> {
[key: string]: Getter<S, R>;
}
這兩個(gè)泛型分別應(yīng)用在本模塊state上和根state上。
export type Getter<S, R> = (state: S, getters: any, rootState: R, rootGetters: any) => any;
MutationTree
我們可以看到mutations的類型MutationTree只接收了一個(gè)泛型。
export interface MutationTree<S> {
[key: string]: Mutation<S>;
}并且這個(gè)泛型只應(yīng)用到本模塊state上。
export type Mutation<S> = (state: S, payload?: any) => any;
ActionTree
我們可以看到actions的類型ActionTree接收了兩個(gè)泛型。
export interface ActionTree<S, R> {
[key: string]: Action<S, R>;
}并且也將這兩個(gè)泛型分別應(yīng)用在本模塊state上和根state上。我們還可以看到,由于action支持對(duì)象和方法形式的寫法,所以Action的類型是ActionHandler和ActionObject的聯(lián)合類型。
export type Action<S, R> = ActionHandler<S, R> | ActionObject<S, R>;
export type ActionHandler<S, R> = (this: Store<R>, injectee: ActionContext<S, R>, payload?: any) => any;
export interface ActionContext<S, R> {
dispatch: Dispatch;
commit: Commit;
state: S;
getters: any;
rootState: R;
rootGetters: any;
}
ModuleTree
我們可以看到modules的類型ModuleTree只接收了一個(gè)泛型。并且將這個(gè)泛型傳遞到了Module里面。
export interface ModuleTree<R> {
[key: string]: Module<any, R>;
}我們可以發(fā)現(xiàn),module的類型和createStore的StoreOptions是非常像的。
因?yàn)槟K本身也有自己的state、getters、actions、mutations、modules
export interface Module<S, R> {
namespaced?: boolean;
state?: S | (() => S);
getters?: GetterTree<S, R>;
actions?: ActionTree<S, R>;
mutations?: MutationTree<S>;
modules?: ModuleTree<R>;
}
了解了vuex4類型 Api接下來我們就進(jìn)入到實(shí)戰(zhàn)環(huán)節(jié)了。
實(shí)戰(zhàn)
首先我們需要使用vuecli創(chuàng)建一個(gè)TypeScript的項(xiàng)目。
整體目錄結(jié)構(gòu)
筆者store整體目錄結(jié)構(gòu)如下:

index.ts和以前的還是一樣,用來創(chuàng)建根store并導(dǎo)出根store。interfaces.ts用來存放store的類型。modules.ts和以前的還是一樣,用來存放模塊。
首先定義根state的類型
// interfaces.ts
type Info = { address: string };
export interface IRootState {
name: string;
age: number;
info: Info;
}在創(chuàng)建store的時(shí)候?qū)⒏鵶tate的類型傳遞進(jìn)去。
// index.ts
import { createStore, Store } from "vuex";
import { InjectionKey } from "vue";
import { IRootState } from "./interfaces";
export default createStore<IRootState>({
state: {
name: "root",
age: 0,
info: { address: "" },
},
getters: {
getRootName(state) {
return state.name;
},
getRootInfo(state) {
return state.info;
},
},
mutations: {},
actions: {},
});并且需要導(dǎo)出key
// index.ts export const key: InjectionKey<Store<IRootState>> = Symbol();
在Vue實(shí)例使用store的時(shí)候?qū)ey一并傳入。
// main.ts
import store, { key } from "@/store";
createApp(App).use(store, key).mount("#app");
在vue組件使用
這樣我們?cè)?code>vue組件就能享受到TypeScript的優(yōu)勢啦。
注意這里的useStore(),也需要我們把key傳遞進(jìn)去。
import { useStore } from "vuex";
import { key } from "@/store";
setup() {
const store = useStore(key);
return {
rootName: store.state.name,
};
},可以看到,我們使用state的時(shí)候就會(huì)被自動(dòng)提示啦。

并且當(dāng)你使用不存在的屬性時(shí)會(huì)在我們編寫代碼的時(shí)候就會(huì)直接報(bào)錯(cuò)提示。

相較js,大大提高了開發(fā)效率不說,還減少了bug。
自定義useStore()方法
如果覺得每次useStore(),還需要我們把key傳遞進(jìn)去麻煩的話,我們可以創(chuàng)建自己的useStore()方法。
// index.ts
import { useStore as baseUseStore } from "vuex";
export function useStore() {
return baseUseStore(key);
}
這樣我們?cè)?code>vue組件使用store的時(shí)候引入自己的useStore方法就可以啦。
import { useStore } from "@/store";
setup() {
const store = useStore();
return {
rootName: store.state.name,
};
},
我們知道,在實(shí)際項(xiàng)目中只創(chuàng)建一個(gè)根store是遠(yuǎn)遠(yuǎn)不夠的。一般我們都會(huì)使用modules。下面筆者介紹下怎么使用modules。
modules的使用
模塊的類型是Module,并且需要傳遞本模塊state類型和根state類型。
本模塊state類型需要傳遞進(jìn)去我們可以理解,但是為什么要傳遞根state類型呢?
因?yàn)槲覀兊?code>getters和actions參數(shù)里面是有rootState的,所以需要引入根state類型。
// modeuls/test1.ts
import { Module } from "vuex";
import { IRootState, ITest1State } from "../interfaces";
const Test1: Module<ITest1State, IRootState> = {
state: {
name: "test1",
count: 0,
},
getters: {
getTest1Name(state) {
return state.name;
},
getAllName(state, rootState) {
return state.name + rootState.age;
},
},
};
export default Test1;創(chuàng)建好模塊后我們需要在根store里面引入進(jìn)去,引入方式和以前還是一樣。
并且我們需要把模塊的state類型一并傳遞到InjectionKey中和根state類型形成交叉類型,并重新生成key。
// index.ts
import { createStore, Store, useStore as baseUseStore } from "vuex";
import { InjectionKey } from "vue";
import { IRootState, ITest1State } from "./interfaces";
import test1 from "./modeuls/test1";
export default createStore<IRootState>({
// ...
modules: {
test1: test1,
// ...多個(gè)模塊,類似
},
});
// 定義模塊類型
type Modules = {
test1: ITest1State;
// ...多個(gè)模塊,類似
};
// 使用交叉類型形成新的key
export const key: InjectionKey<Store<IRootState & Modules>> = Symbol();我們來看看在vue組件中的使用效果。
我們可以發(fā)現(xiàn),當(dāng)我們使用state的時(shí)候,test1模塊也會(huì)被提示出來

并且它里面的屬性也會(huì)被直接提示出來

好了,實(shí)戰(zhàn)環(huán)節(jié)就講述的差不多了,小伙伴們時(shí)候都懂了呢?
總結(jié)
雖然vuex4對(duì)TypeScript有了很好的支持,但是筆者覺得還是不夠的。
比如 使用麻煩,每次需要定義一個(gè)key,還需要把可以傳遞到vue的use方法里面,并且在使用useStore的時(shí)候也還需要將key傳遞進(jìn)去,無疑增加了開發(fā)成本。
其次,這樣的配置并不會(huì)對(duì)getters、mutations、actions生效,只會(huì)對(duì)state有提示。
和pinia比起來,整體使用體驗(yàn)還是會(huì)差很多。如果想學(xué)習(xí)pinia,并想了解pinia和vuex區(qū)別的話可以看看TypeScript Pinia實(shí)戰(zhàn)分享(Vuex和Pinia對(duì)比梳理總結(jié))一文。
到此這篇關(guān)于TypeScript在Vuex4中使用TS實(shí)戰(zhàn)分享的文章就介紹到這了,更多相關(guān)TypeScript Vuex4內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用JS實(shí)現(xiàn)一個(gè)同Excel表現(xiàn)的智能填充算法
這篇文章主要給大家介紹了關(guān)于利用JS實(shí)現(xiàn)一個(gè)同Excel表現(xiàn)的智能填充算法的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-08-08
JavaScript+Canvas實(shí)現(xiàn)酷炫的粒子和流星效果
這篇文章主要為大家詳細(xì)介紹了如何利用JavaScript和Canvas實(shí)現(xiàn)酷炫的粒子和流星動(dòng)畫效果,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2023-01-01
javascript瀏覽器用戶代理檢測腳本實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猨avascript瀏覽器用戶代理檢測腳本實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2017-10-10
設(shè)置iframe的document.designMode后僅Firefox中其body.innerHTML為br
設(shè)置iframe的document.designMode為On可以讓其可編輯,一般用在富文本編輯器組件中。這里僅列出各瀏覽器差異2012-02-02

