Vue 详情页返回列表页,不刷新页面,并且保留列表页原来滚动条所在位置

本文介绍在Vue项目中使用<keep-alive>组件和路由守卫方法,实现在页面间跳转时保持新闻列表页的DOM状态及滚动位置,提升用户体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:

最近公司有个移动端H5的项目,是前后端分离的,所以前端就Vue + Vux来做,项目是用vue-cli3生成的,其中就有这样的一个需求,在新闻列表页中向下滑动后,随别打开一个新闻,进入该新闻的详情页面,当看完后,从详情页返回到新闻列表页。这时,列表页重新请求接口数据,重新渲染DOM,而且滚动条也回到了最顶上的第1个新闻了。这样不仅性能不好,还会影响用户的体验效果。

 

问题分析:

1、从新闻详情页面返回新闻列表页后,新闻列表页重新渲染了DOM。

2、如果在新闻列表页向下滑动后,才进入新闻详情页面时,返回新闻列表页后滚动条回到最顶上了。

 

实现思路:

1、通过<keep-alive>容器组件,将页面缓存起来。

2、当路由跳转到其他页面时: beforeRouteLeave()方法,和 beforeRouteEnter()方法, 来记录 和 恢复滚动条的位置。

 

解决方法:

1、在router.js文件中,给News新闻列表页路由中添加 meta: {   keepAlive: true    //开启缓存  },代码如下:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/Main',
      name: 'Main',
      component: () => import('../views/Main.vue')
    },
    {
      path: '/',
      name: 'News',
      component: () => import('../views/News.vue'),
      meta: {
        keepAlive: true    //开启缓存
      }
    },
    {
      path: '/Info',
      name: 'Info',
      component: () => import('../views/Info.vue')
    }
  ]
})

 

2、在App.vue文件中,在<template>中的<router-view />用<keep-alive>包裹起来,代码如下:

<template>
  <div id="app">
    <keep-alive>
          <!-- 如果当前打开页面的路由中 keepAlive: true (开启了缓存时) -->
          <router-view v-if="$route.meta.keepAlive"></router-view>
    </keep-alive>
        
    <!-- 如果当前打开页面的路由中 没有 或者为 keepAlive: false (关闭缓存时[默认就是false]) -->
    <router-view v-if="!$route.meta.keepAlive"></router-view>
  </div>
</template>

通过以上的两步设置以后,从新闻详情页面再返回新闻列表页时,新闻列表页就不会再重新渲染DOM了。

 

3、在News.vue页面中,添加以下两个监听方法,用于记录离开新闻列表页面时滚动条所在的位置,当返回新闻列表页面时设置滚动条的位置为之前所记录的值。


// 离开路由之前执行的函数

  beforeRouteLeave(to, from, next) {

    // 如果在window中出现的滚动条
    // this.scroll = window.scrollTop;

    //  如果在某个指的元素中出现的滚动条 就在该素中添加ref属性,如:ref="listBox"
    this.scroll = this.$refs.listBox.scrollTop;
    
    next()
  },
  



  // 进入路由之前执行的函数

  beforeRouteEnter(to, from, next) {
    next(vm => {

      // 如果在window中出现的滚动条
      // window.scrollTop = vm.scroll;

      // 如果在某个指的元素中出现的滚动条 就在该素中添加ref属性,如:ref="listBox"
      vm.$refs.listBox.scrollTop = vm.scroll
    })
  }

注:我的滑动区域是在指定的div元素中出现的滚动条

通过以上的三步设置以后,从新闻详情页面再返回新闻列表页时,新闻列表页就不会再重新渲染DOM,返回列表页后,滚动条也回到了原来的位置。

 

扩展:

如何在vue中实时查看滚动条,滚动的位置的值。

 mounted() {
    // 监听window中滚动条的位置
    window.addEventListener('scroll', function(){
     let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop;
      console.log(scrollTop);
    });

    // 监听指定某个元表滚动条的位置
    document.querySelector('#listBox').addEventListener('scroll', function(){
      let scrollTop = this.pageYOffset || this.scrollTop;
      console.log(scrollTop);
}

 

### 解决 UniApp 中列表与详情页之间跳转后返回刷新并定位当前位置 在处理从列表页跳转至详情页返回的情况时,为了保持用户体验的一致性和流畅度,需确保返回列表页丢失之前的滚动位置,并能正常刷新页面获取最新数据。 #### 使用 `onShow` 生命周期钩子实现页面刷新 对于 UniApp 应用,在页面组件中可以通过监听 `onShow` 生命周期函数来实现在每次显示该页面时执行特定逻辑。这有助于确保每当用户回到列表页时都能重新加载最新的数据[^2]: ```javascript export default { onShow() { this.reqTaskList(); }, methods: { async reqTaskList() { try { let res = await uni.request({ url: 'your_api_endpoint', method: 'GET' }); this.taskList = res.data; } catch (error) { console.error('Failed to fetch task list:', error); } } } } ``` #### 记住滚动条的位置 为了让用户能够继续浏览之前查看的内容部分而必每次都从头开始,可以在离开当前页面前往其他页面前保存当前的滚动高度;当再次进入此页面时恢复这个值。具体做法如下所示[^1]: ##### 修改 App.vue 或者全局配置文件中的路由守卫 通过修改应用级别的导航守卫来拦截所有的页面切换操作,从而允许我们在任何地方轻松访问这些功能而无需重复编写相同的代码。 ```javascript // main.js or app.vue import Vue from 'vue'; import Router from './router'; const scrollPositions = {}; Router.beforeEach((to, from, next) => { // Save the current page's scroll position before leaving it. if (from.meta.keepAlive && document.querySelector('.content')) { scrollPositions[from.path] = document.querySelector('.content').scrollTop || 0; } next(); }); Router.afterEach(to => { setTimeout(() => { // Restore saved scroll position after entering a new route that should remember its state. if (scrollPositions[to.path]) { const contentEl = document.querySelector('.content'); if (contentEl) { contentEl.scrollTop = scrollPositions[to.path]; } } }, 0); }); ``` 这里假设 `.content` 是你想要控制其垂直滚动行为的选择器名称,请根据实际情况调整选择器路径。 另外需要注意的是,上述方法适用于大多数场景下的简单需求。如果项目中有更复杂的要求,则可能需要考虑采用更加灵活的方式来进行状态管理,比如 Vuex Store 来集中存储和管理各个视图的状态信息。 #### 防止缓存导致的问题 为了避免由于页面被缓存而导致的数据陈旧或交互异常现象发生,建议使用 `<keep-alive>` 组件包裹 `<router-view>` 并为其设置动态键名作为唯一标识符,这样即使同一个 URL 地址也会因为同的参数组合而被视为两个独立的历史记录项[^3]: ```html <template> <!-- ... --> <keep-alive> <router-view :key="$route.fullPath"></router-view> </keep-alive> <!-- ... --> </template> ``` 这样做仅解决了缓存带来的困扰,同时也提高了应用程序的整体性能表现。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值