You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React Analytics页面实现滚动完整显示单个Dashboard组件需求

实现React Analytics页面Dashboard组件的滚动锁定切换效果

核心思路

将每个Dashboard组件设置为占满整个视口高度,监听滚动/触摸事件判断操作方向,直接平滑滚动到目标组件位置,同时阻止原生滚动的连续触发,确保始终只有一个完整组件显示在视口中。

实现步骤

  1. 基础布局配置

    • 每个Dashboard组件设置height: 100vh,保证单个组件刚好填满屏幕
    • 页面根容器或body设置overflow: hidden,避免原生滚动条干扰
  2. 滚动/触摸事件监听

    • 监听鼠标滚轮事件(wheel)和移动端触摸事件(touchstart/touchend),判断滚动/滑动方向
    • 限制切换范围:只能在0到3(4个组件的索引)之间切换
  3. 平滑滚动与行为拦截

    • 使用window.scrollTo配合behavior: 'smooth'实现组件间的平滑切换
    • 调用event.preventDefault()阻止原生滚动行为,避免一次操作触发多次切换

完整代码示例

import { useEffect, useState } from 'react';

const AnalyticsPage = () => {
  const [currentPanel, setCurrentPanel] = useState(0);
  const totalPanels = 4;

  useEffect(() => {
    // 处理鼠标滚轮
    const handleWheel = (e) => {
      e.preventDefault();
      const isScrollDown = e.deltaY > 0;
      
      if (isScrollDown && currentPanel < totalPanels - 1) {
        setCurrentPanel(prev => prev + 1);
      } else if (!isScrollDown && currentPanel > 0) {
        setCurrentPanel(prev => prev - 1);
      }
    };

    // 处理移动端触摸滑动
    let touchStartY = 0;
    const handleTouchStart = (e) => {
      touchStartY = e.touches[0].clientY;
    };

    const handleTouchEnd = (e) => {
      const touchEndY = e.changedTouches[0].clientY;
      const isSwipeDown = touchEndY > touchStartY;
      
      if (isSwipeDown && currentPanel > 0) {
        setCurrentPanel(prev => prev - 1);
      } else if (!isSwipeDown && currentPanel < totalPanels - 1) {
        setCurrentPanel(prev => prev + 1);
      }
    };

    // 绑定事件
    window.addEventListener('wheel', handleWheel, { passive: false });
    window.addEventListener('touchstart', handleTouchStart);
    window.addEventListener('touchend', handleTouchEnd);

    // 清理事件监听
    return () => {
      window.removeEventListener('wheel', handleWheel);
      window.removeEventListener('touchstart', handleTouchStart);
      window.removeEventListener('touchend', handleTouchEnd);
    };
  }, [currentPanel, totalPanels]);

  // 根据当前索引滚动到对应位置
  useEffect(() => {
    window.scrollTo({
      top: currentPanel * window.innerHeight,
      behavior: 'smooth'
    });
  }, [currentPanel]);

  return (
    <div style={{ overflow: 'hidden', height: '100vh' }}>
      <div className="dashboard-wrapper">
        {/* 替换为你的Dashboard组件 */}
        <div className="dashboard-panel" style={{ height: '100vh' }}>仪表盘 1</div>
        <div className="dashboard-panel" style={{ height: '100vh' }}>仪表盘 2</div>
        <div className="dashboard-panel" style={{ height: '100vh' }}>仪表盘 3</div>
        <div className="dashboard-panel" style={{ height: '100vh' }}>仪表盘 4</div>
      </div>
    </div>
  );
};

export default AnalyticsPage;

额外优化建议

  • 如果Dashboard内容超出视口高度,给组件内部添加overflow-y: auto,实现组件内的独立滚动
  • 添加键盘导航支持:监听keydown事件,通过上下箭头键切换组件,提升 accessibility
  • 加入节流处理(比如用lodash.throttle),避免快速滚动时的频繁切换

内容的提问来源于stack exchange,提问作者John Daison

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 08:35:03