Vue页面跳转优化,loading中间状态和骨架屏

原因

先看一段简单、常规的vue代码。

<template>
  <div v-if="list && list.length>0">
    <div v-for="row in list">
      <span>{{row.xxx}}</span>
      //显示剩下数据
    </div>
  </div>
  <div v-else>
    <div>暂无数据</div>
  </div>
</template>
<script>
export default {
  created() {
    this.ajaxform('/chronic/xxx').then(res => {
      this.list = res.body
    })
  }
}
</script>

这段代码在created生命周期函数内会调用后端接口获取数据,我们假设获取数据的时间需要1秒。那么打开页面后将显示“暂无数据”,1秒后才会显示列表数据,给客户的体验有些不好。这篇文章就来解决这个打开页面先显示暂无数据的问题。

思路

我们希望能加入一个过渡状态,在ajax请求加载数据时显示“数据加载中”,数据加载完成后再根据有无数据来显示列表或是“暂无数据”。当跳转页面时,流程如下图:

但不能所有的ajax请求都显示数据加载中,只能是打开页面后立即执行的ajax请求显示加载中,也就是created、mounted中执行的ajax请求显示加载中。

方案

首先我们需要一个全局变量来储存当前正在执行的ajax请求的数量以及是否是页面刚打开的状态。我将这两个变量存在了store中

const state = {
  pageInit: false,
    // 记录有几个ajax请求正在执行中
  ajaxCount: 0,
}
const mutations = {
  updatePageInit: function (state, pageInit) {
    state.pageInit = pageInit
  },
  updateAjaxCount: function (state, count) {
    state.ajaxCount = state.ajaxCount + count
  }
}
export default {
  namespaced: true,
  state,
  mutations
}

然后因为项目中发起ajax请求的组建使用的是axios,所以可以在axios的request、response拦截器中,对这个数进行加减。请求开始,则对ajaxCount加1,请求成功或是失败对ajaxCount减1

axios.interceptors.request.use(
  config => {
    store.commit('user/updateAjaxCount', 1)
    return config
  },
  error => {
    store.commit('user/updateAjaxCount', -1)
    return Promise.reject(error)
  }
)
axios.interceptors.response.use(
  response => {
    store.commit('user/updateAjaxCount', -1)
    return response
  },
  error => {
    store.commit('user/updateAjaxCount', -1)
    return Promise.reject(error)
  }
)

在router的afterEach函数中对pageInit的值进行更新,也就是设置为刚打开页面的状态

router.afterEach(function (to, from) {
  store.commit('user/updatePageInit', true)
})

再然后在App.vue中要做两件事情

1、在template中,通过私有变量loading的值显示、隐藏<router-view>和加载状态(菊花动图)。

2、对ajaxCount进行watch,当ajaxCount大于0,且是刚进入页面的状态时,设置私有变量loading为true,显示加载中状态。

     当ajaxCount等于0时,也就是ajax请求全部结束时,设置私有变量loading为false,关闭加载中状态,设置pageInit为false,显示数据。

<template>
  <div style='height:100%;'>
    <router-view v-show="!loading"></router-view>
    <div v-show="loading"><img src="xxx/juhua.gif"></div><!-- 转菊花的动图 -->
  </div>
</template>
<script>
export default {
  name: 'app',
  data () {
    return {
      loading: false
    }
  },
  computed: mapState({
    pageInit: state => state.user.pageInit,
    ajaxCount: state => state.user.ajaxCount
  }),
  watch: {
    ajaxCount (count) {
      // count>0表示有ajax请求正在执行中, pageInit表示刚进入新页面, loading表示菊花转的状态
      if (count > 0 && this.pageInit && this.loading === false) {
        this.loading = true
      }
      if (count === 0) {
        this.loading = false
        this.$store.commit('user/updatePageInit', false)
      }
    }
  }
}
</script>

以下是效果图,第一张加载中状态是转菊花的图,第二张加载中状态是骨架屏的图

       

结语

我们加载中状态显示的很简单,只是转菊花,这里也可以做的效果更好一些,例如骨架屏等。

 

 

 

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue中实现页面跳转时加上Loading效果可以通过以下步骤实现: 1. 首先,在main.js中引入Loading组件,并注册为全局组件。可以使用import语句引入Loading组件,然后使用Vue.component()方法注册为全局组件。 2. 在页面中使用Loading组件。在需要加上Loading效果的页面中,使用<template>标签包裹需要显示Loading的内容,并在需要显示Loading的位置使用<v-loading>标签。 3. 在导航守卫中控制Loading的显示和隐藏。在router.beforeEach()事件中,可以根据需要控制Loading的显示和隐藏。可以使用全局变量routerLoading来控制是否启用页面跳转Loading。在跳转开始时调用glo_loading.loadingShow()方法显示Loading,在跳转结束时调用glo_loading.loadingHide()方法隐藏Loading。 4. 可选:可以使用全局的loading简单封装来实现Loading的显示和隐藏。在loading.js文件中,可以定义loadingShow()和loadingHide()方法来显示和隐藏Loading。可以使用ElementUI.Loading.service()方法创建一个Loading实例,并使用loading.close()方法关闭Loading。 综上所述,实现页面跳转时加上Loading效果的代码如下所示: ```javascript // main.js import Loading from './components/Loading.vue'; Vue.component('v-loading', Loading); // 页面中使用Loading组件 <template> <div class="detail"> <v-loading v-if="isLoading"></v-loading> <div class="head">向胃猛冲,芜湖起飞</div> </div> </template> // 导航守卫中控制Loading的显示和隐藏 router.beforeEach((to, from, next) => { routerLoading ? glo_loading.loadingShow() : ''; // 其他逻辑... routerLoading ? glo_loading.loadingHide() : ''; }) // 全局loading简单封装 import ElementUI from 'element-ui'; var loading = null; const loadingShow = () => { loading = ElementUI.Loading.service(loadingConfig); } const loadingHide = () => { loading.close(); } const loadingObj = { loadingShow, loadingHide } export default loadingObj ``` 希望以上解答对您有帮助。 #### 引用[.reference_title] - *1* [VUE 跳转loading动画组件](https://blog.csdn.net/Red_sevenWord/article/details/107353923)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [vue项目全局配置loading页面跳转和ajax请求)](https://blog.csdn.net/John_jian_yo/article/details/105557247)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值