Vue3+TS 当中如何使用 vuex

1,984 阅读4分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 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接收两个参数statepayload作为第二个参数

    //更改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类型,同时接收两个泛型参数IPlayerTypeIRootStore,其中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);
});