一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第 6 天,点击查看活动详情。
介绍
随着 Vue3 正式成为了 Vue-cli 的默认版本,在企业当中新项目使用 Vue3 技术栈来开发的也越越来越多。Vuex 作为 Vue3 的官方状态管理工具,一直在 Vue 的生态当中扮演着很重要的角色。随着 Vue3 的组合式 API 推出,Vuex 也紧接着推出一些系列相对应的 API 来对 Vue3 提供支持,下面我们就来看看在 Vue3+TS 当中,我们该如何使用 Vuex。
创建 Store 实例
index.ts
import { createStore } from "vuex";
import { IRootStore } from "./rootStoreTypes";
const store = createStore<IRootStore>({
state() {
return {
count: 0,
};
},
});
export default store;
rootStoreTypes.ts
export interface IRootStore {
count: number;
}
上面代码当中,我们从 Vuex 当中引入createStore
函数,它可以创建一个Store
的实例。同时它接收一个泛型参数,参数描述了state
当中包含哪些属性与属性是什么类型。createStore<S>(options: StoreOptions<S>): Store<S>
。
Store 构造器选项
state
state
是 Vuex.store 实例的根对象。如果你传入返回一个对象的函数,其返回的对象会被作用根state
。这在你想要重用state
对象,尤其是对于重用modules
来说非常有用。
mutations
mutations
函数的作用是处理需要改变state
当中属性的一些变化,也就是说,如果你需要对state
当中的一些属性做一些操作,Vuex 推荐我们使用mutations
来进行操作。mutations
接收两个参数state
和payload
作为第二个参数
//更改songInfo
CHANGE_SONG_INFO(state, Payload) {
state.songInfo = Payload;
},
actions
actions
可以进行异步操作,一般我们需要对state
当中的数据进行网络请求赋值的时候,我们会使用他来发送异步请求。处理函数总是接受 context
作为第一个参数,payload
作为第二个参数
// 获取歌曲信息
async getSongInfo(context, Payload) {
const {
data: { songs },
} = await getSongDetial(Payload);
context.commit("CHANGE_SONG_INFO", songs);
cacheStore.setSession("songInfo", songs);
//获取歌曲地址
const {
data: { data },
} = await getSongUrl(Payload);
context.commit("CHANGE_SONG_AUDIO_INFO", data);
cacheStore.setSession("songAudioInfo", data);
console.log(songs, data);
},
getters
在getters
当中,我们一般对获取state
当中的属性值的操作,它会返回当前state
当中对应的属性值。
state, // 如果在模块中定义则为模块的局部状态
getters, // 等同于 store.getters
modules
包含了子模块的对象,会被合并到 Store,大概这样
{
key: {
state,
namespaced?,
mutations,
actions?,
getters?,
modules?
},
...
}
import { IRootStore } from "../../rootStoreTypes";
import { IPlayerType, playPayload } from "./playerTypes";
const PlayerModule: Module<IPlayerType, IRootStore> = {
state: {},
getters: {},
mutations: {},
actions: {},
};
export default PlayerModule;
上面的代码当中,创建了一个PlayerModule
对象,对象是Module
类型,同时接收两个泛型参数IPlayerType
和IRootStore
,其中IPlayerType
是当前Store
对象当中state
属性的描述,IRootStore
是对根store
实例上state
的描述。
使用 Vuex
import { useStore } from "vuex";
export default defineComponent({
setup() {
//创建当前的store实例
const Store = useStore();
//通过dispath派发actions当中的属性
Store.dispatch("getNewDiscData");
//通过computed计算属性来获取vuex当中的state属性
const newDiscData = computed(() => Store.getters.getNewDisc);
//如果需要修改state当中的属性,使用commit
Store.commit("CHANGE_SONG_INFO", songs);
},
});
对 Vuex 进行数据持久化
在外面使用 vuex 的时候,当我们一刷新页面,Vuex 当中的状态就会清空,然后页面对出现短暂的空白,在企业的开发当中,这是不可忍受的。所以我们需要对 Vuex 的数据进行持久化。外面封装一个持久化对象
class CacheStore {
//设置session
setSession(key: string, value: unknown) {
window.sessionStorage.setItem(key, JSON.stringify(value));
}
//设置local
setLocal(key: string, value: unknown) {
window.localStorage.setItem(key, JSON.stringify(value));
}
//获取session
getLocal(key: string) {
return window.localStorage.getItem(key);
}
//获取local
getSession(key: string): string {
try {
return window.sessionStorage.getItem(key) as string;
} catch (err) {
return "";
}
}
//删除session单个
removeSession(key: string) {
try {
window.sessionStorage.removeItem(key);
} catch (err) {
return err;
}
}
//删除local单个
removeLocal(key: string) {
try {
window.localStorage.removeItem(key);
} catch (err) {
return err;
}
}
//删除全部session
clearSession() {
window.sessionStorage.clear();
}
//删除全部local
clearLocal() {
window.localStorage.clear();
}
}
//创建实例对象
const cacheStore = new CacheStore();
export default cacheStore;
在actions
当中获取到数据的时候进程持久化操作
// 获取歌曲信息
async getSongInfo(context, Payload) {
const {
data: { songs },
} = await getSongDetial(Payload);
context.commit("CHANGE_SONG_INFO", songs);
cacheStore.setSession("songInfo", songs);
//获取歌曲地址
const {
data: { data },
} = await getSongUrl(Payload);
context.commit("CHANGE_SONG_AUDIO_INFO", data);
//数据持久化
cacheStore.setSession("songAudioInfo", data);
console.log(songs, data);
},
然后我们在获取数据的时候,进行判断,如果 vuex 当中没有数据就到缓存当中去取
getSongInfo(state) {
if (state.songInfo.length !== 0) {
return state.songInfo;
} else {
return JSON.parse(cacheStore.getSession("songInfo"));
}
},
之后我们监听页面的刷新,如果页面在 5 分钟以内没有刷新,那么我们就删除缓存当中的数据
//当页面加载之后,五分钟之后删除session当中的数据
const closeTime = setTimeout(() => {
cacheStore.clearSession();
}, 300000);
window.addEventListener("beforeunload", function () {
clearTimeout(closeTime);
});