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

自定义预约日历性能优化求助:1008个组件渲染卡顿问题

优化28天预约日历渲染卡顿的方案

1. 阻止无意义的组件重渲染

  • 给日程方块组件套上React.memo(),让它只在props(比如选中状态、日程数据)真的变化时才重新渲染。如果props是对象、数组这类引用类型,要用useMemo缓存数据,useCallback缓存事件回调,保证每次传递的引用稳定。
    const ScheduleBlock = React.memo(({ data, isSelected, onSelect }) => {
      // 方块组件逻辑
    });
    
    // 父组件里缓存数据与回调
    const cachedBlockData = useMemo(() => generate28DaysBlocks(), []);
    const handleBlockSelect = useCallback((blockId) => {
      setSelectedBlock(blockId);
    }, []);
    
  • 拆分状态:别把全局选中状态放在顶层父组件,要么把选中状态下沉到方块组件内部,要么用局部状态管理逻辑,只让被点击的方块更新自身状态,避免触发所有1008个组件重渲染。

2. 虚拟滚动(核心优化手段)

用户视野内只能看到部分方块,没必要一次性渲染全部1008个。用虚拟滚动只渲染当前可见区域的组件,其余区域用空白占位模拟高度:

  • 先给日历容器设置固定高度并开启滚动,计算每个方块的宽高以及容器的可视高度。
  • 监听容器滚动事件,算出当前可见的起始行和结束行:比如startRow = Math.floor(scrollTop / blockHeight),endRow = startRow + 可视范围内行数。
  • 只渲染对应行的方块(比如一次渲染5行×36列=180个组件),同时在容器顶部和底部添加空白div占位,保持总高度和完整日历一致。

3. 事件委托替代单个绑定

不给每个方块单独绑onClick,把点击事件绑在日历容器上,通过事件冒泡获取点击的方块元素,再处理选中逻辑。减少事件绑定数量,也避免组件更新时重复绑定事件:

const CalendarContainer = () => {
  const handleContainerClick = (e) => {
    const blockEl = e.target.closest('.schedule-block');
    if (blockEl) {
      const blockId = blockEl.dataset.blockId;
      setSelectedBlock(blockId);
    }
  };

  return (
    <div className="calendar-container" onClick={handleContainerClick}>
      {/* 渲染可见范围内的方块 */}
    </div>
  );
};

4. 批量处理状态更新

如果选中操作会触发多个状态变更,用useReducer或者React的批量更新机制(React 18默认自动批量更新,手动场景可使用unstable_batchedUpdates),减少整体渲染次数。

5. 简化方块组件结构

检查日程方块内部是否有冗余的子组件或复杂逻辑,尽量精简DOM结构。比如把静态文本、通用样式这类内容提取到父组件,避免每个方块重复渲染相同的静态元素。

内容的提问来源于stack exchange,提问作者Zeeshan karim

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 09:10:33