React 保持滚动位置的实现

21 min read

在React应用中,实现用户在浏览列表详情后能够回退到列表并保持原有滚动位置的功能,涉及到滚动位置的保存和恢复,以及滚动事件的监听。以下是一个综合的指南和代码示例,展示如何在React中实现这一功能。

实现策略

  1. 保存滚动位置:在用户离开列表页面时,保存当前的滚动位置。这可以通过监听滚动事件实时完成,也可以在页面卸载时完成。
  2. 恢复滚动位置:当用户从详情页面回退到列表页面时,从保存的位置恢复滚动状态。
  3. 性能优化:考虑到性能影响,对滚动事件监听函数进行节流或防抖处理。

示例代码

列表页面(ListPage.jsx)

import React, { useEffect } from 'react';
import { useLocation } from 'react-router-dom';
import { debounce } from 'lodash';

const ListPage = () => {
  const location = useLocation();

  useEffect(() => {
    // 页面加载时恢复滚动位置
    const savedScrollPosition = sessionStorage.getItem(`${location.pathname}-scrollPosition`) || 0;
    window.scrollTo(0, savedScrollPosition);

    // 定义并应用防抖处理的滚动监听函数
    const handleScroll = debounce(() => {
      sessionStorage.setItem(`${location.pathname}-scrollPosition`, window.scrollY);
    }, 100);

    window.addEventListener('scroll', handleScroll);

    return () => {
      window.removeEventListener('scroll', handleScroll);
    };
  }, [location.pathname]); // 依赖数组包含location.pathname,确保在路由改变时重新设置监听

  return <div>{/* 列表内容 */}</div>;
};

  • 动态内容加载:对于实现了无限滚动的列表,确保加载新内容时更新滚动位置的逻辑不会受到影响。
  • 滚动性能:监听滚动事件可能会影响性能,特别是当滚动事件处理函数中执行复杂操作时。使用lodashdebounce函数可以有效减少这种影响。
  • Session Storage的使用:示例中使用sessionStorage保存滚动位置,确保滚动位置的信息是临时的,并且在浏览器会话结束后被清除。使用${location.pathname}-scrollPosition作为键,可以确保每个页面的滚动位置独立保存和恢复。