Vue+elementUI+Vuex 实现全局loading

1,010 阅读1分钟

业务需求:

  • 请求前全局加载loading,多接口请求结束后再关闭loading;
  • 可指定接口使用;
  • 可全局显示(不遮挡导航栏仅在内容页显示) 或 指定页面使用;

其他:

  • 本文涉及Vue 、ElementUI、 Vuex

1.配置需要全局loading的API

... 
// xxx接口 
export function getList(data,showLoading = false) {
    return service({ 
        url: serverName + '/getList', 
        method: 'post', 
        data: Qs.stringify(data), 
        showLoading,  // 添加showLoading参数
    }) 
} 
...

2.修改axios.js文件

// 请求拦截器
request.interceptors.request.use( config => { 
    if (config.showLoading) { 
        store.dispatch('setLoding', true) // 根据showLoading参数判断是否需要全局显示loaidng
    } 
    ... 
    return config 
}, 
error => { return Promise.reject(error) } ) 

// 响应拦截器
request.interceptors.response.use( (res) => { 
    if (res.showLoading) {
        store.dispatch('setLoding', false) // 响应结束则关闭loading
    }
    ... 
    return result 
}

3.Vuex (记录loadingCount)

  • 添加loading.js文件(本项目文件路径: src\store\modules\loading.js)
const state = {
  loadingCount: 0, 
}

const mutations = {
  SET_LOADING: (state, isShow) => { // 需要全局loading的则loadingCount+1,否则loadingCount-1
    isShow ? ++state.loadingCount : --state.loadingCount
  },
  CLEAR_LOADING: (state) => {
    state.loadingCount = 0  // 当loadingCount等于0时关闭loading效果
  },
}

const actions = {
  setLoding({ commit }, boolean) {
    commit('SET_LOADING', boolean)
  },
  clearLoading({ commit }) {
    commit('CLEAR_LOADING')
  },
}

export default {
  namespaced: true,
  state,
  mutations,
  actions,
}
  • 修改getters.js image.png

4.在页面中添加loading

  • 在layout.vue下或其他组件下添加(这里使用elementUI的loading组件):
<div class="main" v-loading="loading" :element-loading-text="loadingText">
 ...
</div>
import { mapGetters } from 'vuex' 
export default { 
    data () { 
        loading:false, 
        loadingText:'数据加载中...' 
    }, 
    computed: { ...mapState(['loadingCount']) }, 
    watch:{ 
        loadingCount(newval){ 
            this.loading= newval > 0 
    },
}
  • 调用接口页:
 created(){
        this.getData()
    },
    methods: {
        getData(){
            const param={
            ...
            }
            getList(param,true).then(res=>{
                //
            }).finally(()=>{
            })
        }
    }

5.注意:在路由跳转时要关闭全局loading,不然影响交互体验

router.beforeEach((to, from, next) => {
    store.dispatch('clearLoading') //清除全局loading
    ...
    next() 
})

补充其他方法:接口较少可直接使用Promise.all()实现

getData(){
     const loading = this.$loading({
           target: '.content',
           text: '数据加载中...',
         })
     const promiseArray = [
       //1.获取表格列宽
       new Promise((resolve) => {
         if (JSON.stringify(this.colwidthForm) !== '{}') resolve()
         this.getColwidth().then((res) => {
           this.colwidthForm = res || {}
           resolve()
         })
       }),
       //2.查询字段数据
       new Promise((resolve) => {
         this.getFieldInfo().then((res) => {
           this.fields = res || []
           resolve()
         })
       }),
       ...
    ]
     Promise.all(promiseArray).then(() => {
       loading.close() //等所有接口响应完则关闭loading
     })
}