Vue页面返回滚动位置恢复(keep-alive滚动记忆)

 更新时间:2025年09月21日 08:35:18   作者:_AaronWong  
Vue中通过自定义组合式函数useScroll,结合ref响应式状态、生命周期钩子及DOM引用,实现keep-alive缓存组件的滚动位置保存与恢复,优化用户返回时的浏览体验,感兴趣的可以了解一下

在Vue单页应用开发中,我们经常会遇到这样的场景:用户在一个长列表页面滚动浏览了若干项后,点击进入详情页,然后返回期望能够回到之前的滚动位置,而不是重新回到页面顶部。这种用户体验的优化对于内容型应用尤为重要。

Vue的<keep-alive>组件可以缓存页面状态,但它并不自动保存和恢复滚动位置。今天我们就来探讨一种优雅的解决方案。

核心代码解析

import { onActivated, ref } from "vue";
import { onBeforeRouteLeave } from "vue-router";

export function useScroll(targetRef) {
    const scrollTop = ref(0);
    
    onActivated(() => {
        if (targetRef.value) {
            targetRef.value.scrollTop = scrollTop.value
        }
    })
    
    onBeforeRouteLeave(() => {
        if (targetRef.value) {
            scrollTop.value = targetRef.value.scrollTop
        }
    })
}

这个自定义组合式函数useScroll虽然代码简洁,但功能强大且完整。让我们分解一下它的工作原理:

1. 响应式状态管理

使用ref(0)创建了一个响应式的scrollTop变量,用于存储滚动位置。

2. 生命周期钩子运用

  • onActivated: 当被<keep-alive>缓存的组件激活时调用,用于恢复滚动位置
  • onBeforeRouteLeave: 在路由离开之前调用,用于保存当前滚动位置

3. 引用DOM元素

通过targetRef参数接收一个DOM元素的引用,这使得函数可以灵活应用于任何可滚动元素

完整使用示例

<template>
  <div class="product-list" ref="scrollTarget">
    <div v-for="product in products" :key="product.id" class="product-item">
      <h3>{{ product.name }}</h3>
      <p>{{ product.description }}</p>
      <button @click="goToDetail(product)">查看详情</button>
    </div>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useScroll } from '@/composables/useScroll'

const router = useRouter()
const scrollTarget = ref(null)
const products = ref([...]) // 产品列表数据

// 使用滚动记忆功能
useScroll(scrollTarget)

const goToDetail = (product) => {
  router.push(`/product/${product.id}`)
}
</script>

<style scoped>
.product-list {
  height: 100vh;
  overflow-y: auto;
}
</style>

路由配置要点

为了使<keep-alive>生效,需要在路由配置和组件渲染中做相应设置:

// router.js
const routes = [
  {
    path: '/products',
    component: () => import('@/views/ProductsView.vue'),
    meta: { keepAlive: true } // 添加元信息标识需要缓存的页面
  }
  // ...其他路由
]
<!-- App.vue -->
<template>
  <router-view v-slot="{ Component, route }">
    <keep-alive>
      <component 
        :is="Component" 
        v-if="route.meta.keepAlive" 
        :key="route.name"
      />
    </keep-alive>
    <component 
      :is="Component" 
      v-if="!route.meta.keepAlive" 
      :key="route.name"
    />
  </router-view>
</template>

进阶优化

1. 多滚动容器支持

实际应用中,一个页面可能有多个滚动区域,我们可以扩展useScroll来支持这种情况:

export function useScroll(targetRef, identifier = 'default') {
    const scrollPositions = ref({});
    
    onActivated(() => {
        if (targetRef.value) {
            targetRef.value.scrollTop = scrollPositions.value[identifier] || 0;
        }
    })
    
    onBeforeRouteLeave(() => {
        if (targetRef.value) {
            scrollPositions.value[identifier] = targetRef.value.scrollTop;
        }
    })
}

2. 防抖处理

对于高频触发滚动事件的情况,可以添加防抖优化:

import { debounce } from 'lodash-es';

export function useScroll(targetRef) {
    const scrollTop = ref(0);
    
    onActivated(() => {
        if (targetRef.value) {
            targetRef.value.scrollTop = scrollTop.value;
        }
    })
    
    const saveScrollPosition = debounce(() => {
        if (targetRef.value) {
            scrollTop.value = targetRef.value.scrollTop;
        }
    }, 100);
    
    onMounted(() => {
        if (targetRef.value) {
            targetRef.value.addEventListener('scroll', saveScrollPosition);
        }
    });
    
    onUnmounted(() => {
        if (targetRef.value) {
            targetRef.value.removeEventListener('scroll', saveScrollPosition);
        }
    });
}

到此这篇关于Vue页面返回滚动位置恢复(keep-alive滚动记忆)的文章就介绍到这了,更多相关Vue 滚动位置恢复内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • vue项目中使用axios遇到的相对路径和绝对路径问题

    vue项目中使用axios遇到的相对路径和绝对路径问题

    这篇文章主要介绍了vue项目中使用axios遇到的相对路径和绝对路径问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • vue修改打包配置如何实现代码打包后的自定义命名

    vue修改打包配置如何实现代码打包后的自定义命名

    这篇文章主要介绍了vue修改打包配置如何实现代码打包后的自定义命名,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-05-05
  • Vue.js图片预览插件使用详解

    Vue.js图片预览插件使用详解

    Vue是一套用于构建用户界面的渐进式框架。这篇文章主要介绍了Vue.js图片预览插件的相关知识,非常不错,具有一定的参考借鉴价值,需要的朋友可以参考下
    2018-08-08
  • vue.js的简单自动求和计算实例

    vue.js的简单自动求和计算实例

    今天小编就为大家分享一篇vue.js的简单自动求和计算实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue+vant实现购物车全选和反选功能

    vue+vant实现购物车全选和反选功能

    这篇文章主要为大家详细介绍了vue+vant实现购物车全选和反选功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-11-11
  • Vue监听滚动实现锚点定位(双向)示例

    Vue监听滚动实现锚点定位(双向)示例

    今天小编大家分享一篇Vue监听滚动实现锚点定位(双向)示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • 如何解决elementUI打包上线后icon图标偶尔乱码问题

    如何解决elementUI打包上线后icon图标偶尔乱码问题

    文章描述了在使用若依框架开发过程中遇到的图标乱码问题,通过分析发现是由于sass编译器将Unicode编码转换为明文导致的,文章提供了四种处理方法:使用css-unicode-loader、升高sass版本、替换element-ui的样式文件和更换打包压缩方式
    2025-01-01
  • Vue 解决在element中使用$notify在提示信息中换行问题

    Vue 解决在element中使用$notify在提示信息中换行问题

    这篇文章主要介绍了Vue 解决在element中使用$notify在提示信息中换行问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-11-11
  • vue实现商品列表的无限加载思路和步骤详解

    vue实现商品列表的无限加载思路和步骤详解

    这篇文章主要介绍了vue实现商品列表的无限加载思路和步骤详解,基础思路是触底条件满足之后 page++,拉取下一页数据,结合实例代码给大家介绍的非常详细,需要的朋友可以参考下,
    2024-06-06
  • axios在Vue3中的使用实例代码

    axios在Vue3中的使用实例代码

    Axios是一个基于Promise的HTTP客户端,用于浏览器和Node.js,这篇文章主要介绍了axios在Vue3中的使用,需要的朋友可以参考下
    2023-07-07

最新评论