全局状态设置

125 阅读1分钟

在vuex 设置 loading 状态处理

import { Module } from 'vuex'
import { GlobalDataProps } from './index'
export interface GlobalStatus {
  opNames: { [key: string]: boolean };
  requestNumber: number;
  error: {
    status: boolean;
    message?: string;
  };
}

const global: Module<GlobalStatus, GlobalDataProps> = {
  state: {
    requestNumber: 0,
    opNames: {},
    error: {
      status: false
    }
  },
  mutations: {
    startLoading (state, { opName }) {
      state.requestNumber++
      if (opName) {
        state.opNames[opName] = true
      }
    },
    finishLoading (state, { opName }) {
      setTimeout(() => {
        state.requestNumber--
        delete state.opNames[opName]
      }, 1000)
    },
    setError(state, e) {
      state.error = e
    }
  },
  getters: {
    isLoading: (state) => {
      return state.requestNumber > 0
    },
    isOpLoading: state => (opName: string) => {
      return state.opNames[opName]
    }
  }
}

export default global

axios 拦截器设置 处理请求loading

import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios'
export type ICustomAxiosConfig = AxiosRequestConfig & {
  opName?: string;
}
axios.interceptors.request.use(config => {
  const newConfig = config as ICustomAxiosConfig
  store.commit('setError', { status: false, message: ''})
  store.commit('startLoading', { opName: newConfig.opName })
  return config
})
axios.interceptors.response.use((resp: AxiosResponse<RespData>) => {
  const { config, data } = resp
  const newConfig = config as ICustomAxiosConfig
  store.commit('finishLoading', { opName: newConfig.opName })
  const { errno, message } = data
  if (errno && errno !== 0) {
    store.commit('setError', { status: true, message })
    return Promise.reject(data)
  }
  return resp
}, (e: AxiosError) => {
  const newConfig = e.config as ICustomAxiosConfig
  store.commit('setError', { status: true, message: '服务器错误' })
  store.commit('finishLoading', { opName: newConfig.opName })
  return Promise.reject(e)
})

**### 注意: 需要在其他地方设置 opName 这个请求参数的 **

 const newConfig = { ...config, data, opName: commitName }
  const newConfig = { ...config, data, opName: commitName }

在项目中使用

  const isLoading = computed(() => store.getters.isOpLoading('fetchTemplates'))

将全局错误和读取添加到跟组件

<template>
  <div class="app-container">
    <a-spin v-if="showLoading" tip="读取中" class="global-spinner"/>
    <router-view/>
  </div>
</template>

<script lang="ts">
import { defineComponent, computed, watch } from 'vue'
import { useStore } from 'vuex'
import { useRoute } from 'vue-router'
import { message } from 'ant-design-vue'
import { GlobalDataProps } from './store/index'
export default defineComponent({
  name: 'App',
  setup() {
    const store = useStore<GlobalDataProps>()
    const route = useRoute()
    const isLoading = computed(() => store.getters.isLoading)
    const showLoading = computed(() => isLoading.value && !route.meta.disableLoading)
    const error = computed(() => store.state.global.error)
    watch(() => error.value.status, (errorValue) => {
      if (errorValue) {
        message.error(error.value.message || '未知错误', 2)
      }
    })
    return {
      showLoading
    }
  }
})
</script>
<style>
.app-container .global-spinner {
  position: fixed;
  top: 10px;
  right: 50%;
}
</style>