后台管理系统loading的局部刷新

 

后台管理系统loading的局部刷新

 

在一次vue+element-ui后台管理系统的项目中,遇到这样一个问题,引入element-ui加载框后,loading会占满整个屏幕,虽然通过改变路由实现了局部刷新,但是loading的全屏刷新,让人看上去很是不爽,以为是全局刷新。再一个问题就是,一个页面中可能含有的多个请求,在拦截器汇总设置关闭loading后,会出现的问题就是,有些数据还是空的,但是loading框就已经关闭了我们需要实现的是所有请求完成后关闭loading。所以这是另一个问题。 


 

所以为了解决这两个问题做此总结,帮助更多的小伙伴脱坑。

如果要实现全局的刷新则可以查看博主的另一片总结:传送门

 

没有思路就没有出路,先说思路:

 

局部的loading框的出现,element-ui在vue中引入后,就会默认在vue原型链上挂在一个loaiding方法,可以通过vue.prototype.$loading看到,解决问题的关键就在这个方法中,该方法中可以设置这么几个属性lock,text,target,background,我们搞清楚这些,问个问题也就迎刃而解。lock可以看作是loading的开关,text则是loading的文本的提示信息。target则是根据类型显示需要出现loading的区域。background则是loading的bgcolor

 

所有请求完成后再关闭loading,默认大家都知道vue拦截器。解决思路比较简单,创建一个定时器,在request时,num++,在response时num--当num<=0时,则所有请求都有了结果,这个时候我们就可以关闭loading了。 

情景及Demo

后台管理系统,header,aside,main,除了loading,404外,实现main的局部刷新,且所有请求完成后再关闭loading框。 先看我们的网络请求层,封装的fetch.js文件. 

 
  1. import axios from 'axios'
  2. import { Message} from 'element-ui'
  3. import router from '../router/permission'
  4. import Vue from 'vue'
  5.  
  6. // loading框设置局部刷新,且所有请求完成后关闭loading框
  7. let loading;
  8. function startLoading() {
  9. loading = Vue.prototype.$loading({
  10. lock: true,
  11. text: "Loading...",
  12. target: document.querySelector('.loading-area')//设置加载动画区域
  13. });
  14. }
  15. function endLoading() {
  16. loading.close();
  17. }
  18.  
  19. //声明一个对象用于存储请求个数
  20. let needLoadingRequestCount = 0;
  21. function showFullScreenLoading() {
  22. if (needLoadingRequestCount === 0) {
  23. startLoading();
  24. }
  25. needLoadingRequestCount++;
  26. };
  27. function tryHideFullScreenLoading() {
  28. if (needLoadingRequestCount <= 0) return;
  29. needLoadingRequestCount--;
  30. if (needLoadingRequestCount === 0) {
  31. endLoading();
  32. }
  33. };
  34.  
  35. // 请求拦截
  36. axios.interceptors.request.use(config => {
  37. showFullScreenLoading();
  38. return config;
  39. }, err => {
  40. tryHideFullScreenLoading();
  41. Message.error({ message: '请求超时!' });
  42. return Promise.resolve(err);
  43. })
  44. // 响应拦截
  45. axios.interceptors.response.use(res => {
  46. tryHideFullScreenLoading();
  47. if (res.data.code == 200) {
  48. return res.data.result;
  49. } else if (res.data.code == 401) {
  50. router.push('/login');
  51. return Promise.reject(res);
  52. } else if (res.data.code == 201) {
  53. Message.error({ message: res.data.msg });
  54. return Promise.reject(res);
  55. }
  56. return Promise.reject(res);
  57. }, err => {
  58. tryHideFullScreenLoading();
  59. if (err.response.status == 504 || err.response.status == 404) {
  60. Message.error({ message: '服务器被吃了⊙﹏⊙∥' });
  61. } else if (err.response.status == 403) {
  62. Message.error({ message: '权限不足,请联系管理员!' });
  63. } else {
  64. Message.error({ message: '未知错误' });
  65. }
  66. return Promise.reject(err);
  67. })
  68.  
  69. let base = '';
  70. export const postRequest = (url, params) => {
  71. return axios({
  72. method: 'post',
  73. url: `${base}${url}`,
  74. data: params,
  75. transformRequest: [function (data) {
  76. let ret = ''
  77. for (let it in data) {
  78. ret += encodeURIComponent(it) + '=' + encodeURIComponent(data[it]) + '&'
  79. }
  80. return ret
  81. }],
  82. headers: {
  83. 'Content-Type': 'application/x-www-form-urlencoded'
  84. }
  85. });
  86. }
  87. export const getRequest = (url, data = '') => {
  88. return axios({
  89. method: 'get',
  90. params: data,
  91. url: `${base}${url}`
  92. });
  93. }

 

下来我们就需要查看我们的主入口文件Home.vue. 

 

 
  1. <template>
  2. <!-- 布局 -->
  3. <el-container>
  4. <el-header class="header-wraper" >
  5. <admin-header></admin-header>
  6. </el-header>
  7. <el-container class="container">
  8. <el-aside >
  9. <admin-aside></admin-aside>
  10. </el-aside>
  11. <el-main class="loading-area">
  12. <keep-alive>
  13. <router-view v-if="this.$route.meta.keepAlive"></router-view>
  14. </keep-alive>
  15. <router-view v-if="!this.$route.meta.keepAlive"></router-view>
  16. </el-main>
  17. </el-container>
  18. </el-container>
  19. </template>
  20.  
  21. <script>
  22. import AdminAside from '@/components/Commons/Aside/index';
  23. import AdminHeader from '@/components/Commons/Header/index'
  24. export default {
  25. components: {
  26. AdminAside,
  27. AdminHeader
  28. },
  29. data () {
  30. return {}
  31. },
  32. }
  33. </script>
  34.  
  35. <style lang="less" scoped>
  36. .header-wraper {
  37. width: 100%;
  38. height: 70px;
  39. border-bottom: 1px solid #ccc;
  40. overflow: hidden;
  41. }
  42. .container {
  43. width: 100%;
  44. height: 100%;
  45. }
  46. </style>

关键实现以上两部就可实现头部预览效果局部刷新。