当前位置: 首页 > article >正文

Vue 3 自定义 Hook:实现页面数据刷新与滚动位置还原

存在一个场景:

在列表页滚动查看某一条卡片时,从卡片进入详情页面后,返回时希望页面能够滚动回原来的卡片位置,而不是顶部或其他位置。应该怎么办呢?

1. 方法简述

1.1 整体流程
  1. 离开页面时:
    • 记录当前滚动位置。
  2. 返回页面时:
    • 判断是否需要刷新数据和还原滚动位置。
    • 如果需要:
      1. 调用指定的刷新方法。
      2. 将滚动位置还原到离开时的值。
1.2 核心处理
import { computed, ref } from 'vue';
export default function useRefreshScroll({
  fromList,
  scrollDomRef,
  queryDomRef = null,
  queryFn = 'onRefresh',
}) {
  // 存储离开时的位置
  const preScrollTop = ref(0);
  const scrollDom = computed(() => (scrollDomRef.value instanceof HTMLElement ? scrollDomRef.value : scrollDomRef.value?.$el));

  // 页面进入前判断是否需要还原位置
  const beforeEnter = async (to, from, next) => {
    if (fromList.includes(from.name as string)) {
      const resultQueryDomRef = queryDomRef ?? scrollDomRef;

      const refreshFn = resultQueryDomRef.value?.[queryFn];
      if (refreshFn) {
        await refreshFn();
      }
      setTimeout(() => {
        if (scrollDom.value) {
          scrollDom.value.scrollTop = preScrollTop?.value;
        }
      }, 300); // 观感考虑设置为300
    }
    next();
  };

  // 记录离开时的位置 scrollTop
  const beforeLeave = (to, from, next) => {
    preScrollTop.value = scrollDom?.value?.scrollTop ?? 0;
    next();
  };

  return {
    beforeLeave,
    beforeEnter,
  };
}
1.3 具体使用方法
<template>
  <div ref="scrollDomRef" class="scroll-container">
    <!-- 这里是滚动内容 -->
  </div>
</template>

<script>
import { ref } from 'vue';
import useRefreshScroll from './path/to/useRefreshScroll';

export default {
  name: 'MyComponent',
  setup() {
    const scrollDomRef = ref(null); // 滚动容器的 ref

    const { beforeLeave, beforeEnter } = useRefreshScroll({
      // 假设从 'home' 或 'profile' 页面跳转过来时需要恢复滚动位置
      fromList: ['home', 'profile'],
      scrollDomRef,
      queryFn: 'onRefresh',
    });

    // 这里可以处理路由守卫...

    return {
      scrollDomRef,
      beforeLeave,
      beforeEnter,
    };
  },
};
</script>

2. 方法介绍

作用:根据条件判断是否需要刷新页面数据,并将页面滚动位置恢复到离开时的锚点位置。

参数如下:

/**
 * @param fromList:Array<string>,页面导航的前置页面 name 列表。如果从这些页面返回,则触发数据刷新和滚动位置恢复逻辑。
 * @param scrollDomRef:Ref,表示滚动容器的引用,可能是一个 DOM 节点或 Vue 组件实例。
 * @param queryDomRef:Ref,用于调用数据刷新方法的组件引用,默认值是 scrollDomRef。
 * @param queryFn:string,需要调用的刷新数据的方法名称,默认是 'onRefresh'。
 * @return {*}
 */

部分代码注释:

1、scrollDom:返回滚动容器的实际 DOM 元素。如果 scrollDomRef.value 是一个 DOM 元素,则直接返回,如果其是 Vue 组件实例,则尝试获取根 DOM 元素(使用 $el )。

const scrollDom = computed(() => 
  (scrollDomRef.value instanceof HTMLElement ? scrollDomRef.value : scrollDomRef.value?.$el)
);

2、beforeEnter 和 beforeLeave Vue Router 的路由守卫

在 beforeEnter 中,首先检查页面是否从某个特定页面(由 fromList 定义)跳转过来。如果是的话,它会检查是否需要执行 onRefresh 等操作,并且在视图渲染后恢复滚动位置。

在 beforeLeave 中,记录了当前页面的滚动位置 scrollTop,以便在进入下一个页面时恢复这个位置。

这两个方法会在 Vue Router 的生命周期钩子 beforeRouteEnter、beforeRouteLeave 中使用。

3、next() 是 Vue Router 生命周期钩子中的回调函数,用来继续路由的生命周期。

eg:在 beforeEnter 和 beforeLeave 调用,通知 Vue Router 继续执行路由切换操作。

总结:

通过 Vue 的响应式 API 和导航守卫,实现了动态刷新与滚动位置恢复的功能,更好的提升用户体验。


http://www.kler.cn/a/512954.html

相关文章:

  • 【2024年华为OD机试】(A卷,100分)- 匿名信 (Java JS PythonC/C++)
  • 【python】基于决策树,SVM 和 神经网络 预测银行客户流失
  • 认识 Milvus 向量数据库
  • Linux Bash 中使用重定向运算符的 5 种方法
  • DuckDB:Golang操作DuckDB实践指南
  • 20250120面试鸭特训营第28天
  • 计算机网络 (48)P2P应用
  • feign调用跳过HTTPS的SSL证书校验配置详解
  • Android 右键后无Java class创建
  • 2024:在成长、创作与生活中找到星光
  • SSM宠物医院信息管理系统
  • C# 的 NLog 库高级进阶
  • PyTorch框架——基于深度学习YOLOv8神经网络学生课堂行为检测识别系统
  • TaskBuilder前后端通讯的数据格式
  • 扬帆数据结构算法之舟,启航C++探索征途——LeetCode深度磨砺:顺序表技术精进实践
  • 持续集成工具Jenkins(一)
  • 服务器机房迁移,centos系统root无法登录,也无法联网等问题
  • Pandas 数据分析(二)【股票数据】
  • Windows7搭建Hadoop-2.7.3源码阅读环境问题解决列表
  • Maven私服-Nexus3安装与使用