ant-design / pro-components

🏆 Use Ant Design like a Pro!
https://pro-components.antdigital.dev
MIT License
4.04k stars 1.29k forks source link

🧐[问题] pro-layout 带的 menu , 展开闭合时, 非常卡顿, 看了下 cpu 占用, 不知道哪一块的问题 #1852

Closed opamine closed 3 years ago

opamine commented 3 years ago

🧐 问题描述

使用的是 pro-layout 带的 menu , 展开闭合时, 非常卡顿, 看了下 cpu 占用, 不知道哪一块的问题

💻 示例代码

BasicLayout 文件如下:

/**
 * Ant Design Pro v4 use `@ant-design/pro-layout` to handle Layout.
 * You can view component api by:
 * https://github.com/ant-design/ant-design-pro-layout
 */
import ProLayout, { PageContainer } from '@ant-design/pro-layout';
import React, { useEffect, useMemo, useRef } from 'react';
import { Link, useIntl, connect, history } from 'umi';
import { Result, Button } from 'antd';
import { SmileOutlined, HeartOutlined } from '@ant-design/icons';
import Authorized from '@/utils/Authorized';
import RightContent from '@/components/GlobalHeader/RightContent';
import { getMatchMenu } from '@umijs/route-utils';
import logo from '../assets/logo.svg';

const IconMap = {
  smile: <SmileOutlined />,
  heart: <HeartOutlined />,
};

// 用于为从服务端请求来的菜单添加通过 icon 字段 匹配 Icon (字体图标)
const loopMenuItem = (menuList) =>
  menuList.map(({ icon, children, ...item }) => ({
    ...item,
    icon: icon && IconMap[icon],
    children: children && loopMenuItem(children),
  }));

const noMatch = (
  <Result
    status={403}
    title="403"
    subTitle="Sorry, you are not authorized to access this page."
    extra={
      <Button type="primary">
        <Link to="/user/login">Go Login</Link>
      </Button>
    }
  />
);

/**
 * use Authorized check all menu item
 */

const BasicLayout = (props) => {
  const {
    dispatch,
    children,
    settings,
    location = {
      pathname: '/',
    },
    menuList,
    loading,
  } = props;
  const menuDataRef = useRef([]);

  useEffect(() => {
    if (dispatch) {
      dispatch({
        type: 'menu/menuTree',
        payload: {
          menuParentId: '22248',
        },
      });
      dispatch({
        type: 'dict/types',
      });
    }
  }, []);
  /**
   * init variables
   */

  const handleMenuCollapse = (payload) => {
    if (dispatch) {
      dispatch({
        type: 'global/changeLayoutCollapsed',
        payload,
      });
    }
  };

  // get children authority
  const authorized = useMemo(
    () =>
      getMatchMenu(location.pathname || '/', menuDataRef.current).pop() || {
        authority: undefined,
      },
    [location.pathname],
  );
  const { formatMessage } = useIntl();

  return (
    <ProLayout
      logo={logo}
      formatMessage={formatMessage}
      {...props}
      {...settings}
      onCollapse={handleMenuCollapse}
      onMenuHeaderClick={() => history.push('/')}
      menuItemRender={(menuItemProps, defaultDom) => {
        if (
          menuItemProps.isUrl ||
          !menuItemProps.path ||
          location.pathname === menuItemProps.path
        ) {
          return defaultDom;
        }

        return <Link to={menuItemProps.path}>{defaultDom}</Link>;
      }}
      breadcrumbRender={(routers = []) => [
        {
          path: '/',
          breadcrumbName: formatMessage({
            id: 'menu.home',
          }),
        },
        ...routers,
      ]}
      itemRender={(route, params, routes, paths) => {
        const first = routes.indexOf(route) === 0;
        return first ? (
          <Link to={paths.join('/')}>{route.breadcrumbName}</Link>
        ) : (
          <span>{route.breadcrumbName}</span>
        );
      }}
      menuDataRender={() => loopMenuItem(menuList)}
      rightContentRender={() => <RightContent />}
      postMenuData={(menuData) => {
        menuDataRef.current = menuData || [];
        return menuData || [];
      }}
      menu={{ locale: false, loading }}
    >
      <Authorized authority={authorized.authority} noMatch={noMatch}>
        <PageContainer header={{ title: '' }}>{children}</PageContainer>
      </Authorized>
    </ProLayout>
  );
};

export default connect(({ global, settings, menu, loading }) => ({
  collapsed: global.collapsed,
  settings,
  menuList: menu.menuList,
  loading: loading.effects['menu/menuTree'],
}))(BasicLayout);

🚑 其他信息

↓↓↓↓↓↓↓↓↓↓↓↓

图片

chenshuai2144 commented 3 years ago

写标题

opamine commented 3 years ago

@chenshuai2144

chenshuai2144 commented 3 years ago

应该不是menu的问题把,这么搞得占用不至于。。

你用devtool的 性能工具搞个火焰图出来

opamine commented 3 years ago

图片 图片 图片 图片

🖥️ : 我执行的是 闭合 -> 展开 -> 闭合 -> 展开

🧮 : 以上四张图是 前两步操作的截图

opamine commented 3 years ago

@chenshuai2144 大哥查收

chenshuai2144 commented 3 years ago

这个不至于那么高的cpu占用的,chrome 在偷偷干别的事情把

你试试用户用火狐

opamine commented 3 years ago

这个不至于那么高的cpu占用的,chrome 在偷偷干别的事情把

你试试用户用火狐

我这边试了下火狐,也是这样。 这边大概知道问题所在了, 我稍后整理一下发出来

opamine commented 3 years ago

"@ant-design/pro-layout": 6.14.0 "@ant-design/pro-table": 2.28.0

图片

我这边把 pro-table 的 request 属性去掉, 不从服务器请求数据, 上面的情况就不存在了 ❓

opamine commented 3 years ago

"@ant-design/pro-layout": 6.14.0 "@ant-design/pro-table": 2.28.0

图片

我这边把 pro-table 的 request 属性去掉, 不从服务器请求数据, 上面的情况就不存在了 ❓

好像还不是这个原因,我再研究一下吧,

chenshuai2144 commented 3 years ago

chrome 有自己的任务管理器,去里面看看把

samotoo commented 2 years ago

你好,

这边有类似的问题,侧边栏menu展开收起动画有明显的卡顿,把ProTable的scroll prop去掉,就不会卡顿了,应该如何解决呢? 使用的组件版本: "@ant-design/pro-layout": "^6.21.0", "@ant-design/pro-table": "^2.43.0",

samotoo commented 2 years ago

这个问题貌似和#3113是同一个问题,那个issue里提示用sCU来解决更新频率高的问题,请问能否给个例子说明一下。 宽度变化导致的更新并不是因为父组件传给ProTable的prop变化了,而是因为ProTable内部的更新机制,该如何从外部去控制这个内部机制呢?

qidasheng369 commented 2 years ago

有同样的问题,菜单展开/收起,明显有卡顿。 使用的antdPro-smiple架子; 对应的版本分别为protable:"^2.56.0",和layout:^6.26.0", 先埋个坑,后续定位问题,坐等有大佬给出解决方案。。

qidasheng369 commented 2 years ago

去掉scroll这个宽度的属性之后,就很流畅;不确定是不是这个属性导致layout需要计算宽度,产生的性能问题。。

microJ commented 2 years ago

如果需要 scroll 横向滚动的朋友,可以尝试使用 scroll={{x: 'max-content'}},比 scroll={{x: true}} 掉帧要减少很多。

panyushan-jade commented 1 year ago

请问解决了嘛,我也有这个问题 🙏

microJ commented 1 year ago

请问解决了嘛,我也有这个问题 🙏

升级版本试下

qingweiSun commented 1 year ago

现在也还是卡呀

chaovbz commented 10 months ago

scroll={{x: 120}}