从零开始构建可复用的Menu菜单组件实战经验分享

司徒子晴 组件 阅读 3,021
赞 48 收藏
二维码
手机扫码查看
反馈

优化前:卡得不行

最近在做一个项目,里面有一个挺复杂的菜单组件。这个菜单里有几十个选项,还有多级子菜单,结果性能问题就来了。用户一打开页面,菜单加载得特别慢,有时候甚至卡顿到无法忍受。说实话,我第一次看到这情况时,心里那个急啊。加载时间直接飙到5秒,用户体验简直糟糕透顶。

从零开始构建可复用的Menu菜单组件实战经验分享

找到症结了!

要想解决问题,首先得找到问题所在。我用了几个常用的工具来定位问题:

  • Chrome DevTools:这个不用说,简直是前端开发者的必备神器。通过Performance面板,我看到了CPU和内存的使用情况,发现菜单渲染时CPU占用率特别高。
  • Lighthouse:这个工具可以帮你分析页面的整体性能,跑了一下报告,发现确实有很多性能瓶颈。

通过这些工具,我发现主要的问题在于菜单的DOM结构过于复杂,每次渲染都需要大量计算,导致性能下降。另外,还有一些不必要的CSS动画也拖慢了加载速度。

优化后:流畅多了

找到了问题,接下来就是优化了。试了几种方案,最后这个效果最好。

1. 优化DOM结构

原来的菜单结构是这样的:

<nav class="menu">
  <ul>
    <li>一级菜单
      <ul>
        <li>二级菜单
          <ul>
            <li>三级菜单</li>
          </ul>
        </li>
      </ul>
    </li>
  </ul>
</nav>

这种嵌套太多,浏览器解析起来很吃力。我改成了扁平化结构,用JS动态生成子菜单:

<nav class="menu">
  <ul>
    <li>一级菜单</li>
    <li>二级菜单</li>
    <li>三级菜单</li>
  </ul>
</nav>

然后在JS中处理菜单的展开和折叠:

document.querySelectorAll('.menu li').forEach(item => {
  item.addEventListener('click', (e) => {
    e.preventDefault();
    const subMenu = e.target.nextElementSibling;
    if (subMenu && subMenu.classList.contains('submenu')) {
      subMenu.classList.toggle('hidden');
    }
  });
});

这样改动后,DOM结构简单了很多,浏览器解析起来也快了不少。

2. 去掉不必要的CSS动画

原来菜单有个展开动画,虽然看起来很酷,但对性能影响很大。我把这些动画去掉了,改成简单的过渡效果:

.menu li {
  transition: all 0.3s ease;
}

这样既保持了视觉效果,又不会拖慢加载速度。

3. 使用虚拟滚动

菜单项很多的时候,一次性渲染所有内容会非常消耗性能。我用了虚拟滚动技术,只渲染当前可见的部分,大幅提升了性能:

import { createRef } from 'react';
import { List, AutoSizer, WindowScroller } from 'react-virtualized';

const Menu = () => {
  const listRef = createRef();

  return (
    <WindowScroller ref={listRef}>
      {({ height, isScrolling, onChildScroll, scrollTop }) => (
        <AutoSizer disableHeight>
          {({ width }) => (
            <List
              height={height}
              rowCount={items.length}
              rowHeight={30}
              rowRenderer={({ index, key, style }) => (
                <div key={key} style={style}>
                  {items[index]}
                </div>
              )}
              width={width}
              isScrolling={isScrolling}
              onScroll={onChildScroll}
              scrollTop={scrollTop}
            />
          )}
        </AutoSizer>
      )}
    </WindowScroller>
  );
};

这个改动的效果非常明显,加载时间从5秒降到了800毫秒左右。

性能数据对比

优化前后,性能数据变化如下:

指标 优化前 优化后
加载时间 5秒 800毫秒
CPU占用率 90% 40%
内存占用 150MB 80MB

从数据上看,优化后的性能提升非常明显,用户体验也好了很多。

以上是我的优化经验,有更好的方案欢迎交流

优化过程中踩了不少坑,也学到了不少东西。希望我的这些经验能帮到你。如果有更好的优化方案,欢迎在评论区交流。后续我会继续分享这类实战经验,希望能对你有所帮助。

本文章不代表JZTHEME立场,仅为作者个人观点 / 研究心得 / 经验分享,旨在交流探讨,供读者参考。
发表评论

暂无评论