Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,6 @@ ReactDOM.render(
<th>vertical</th>
<td>one of ["horizontal","inline","vertical-left","vertical-right"]</td>
</tr>
<tr>
<td>activeKey</td>
<td>String</td>
<th></th>
<td>initial and current active menu item's key.</td>
</tr>
<tr>
<td>defaultActiveFirst</td>
<td>Boolean</td>
<th>false</th>
<td>whether active first menu item when show if activeKey is not set or invalid</td>
</tr>
<tr>
<td>multiple</td>
<td>Boolean</td>
Expand Down
37 changes: 32 additions & 5 deletions assets/index.less
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,6 @@
border-bottom: 1px solid #dedede;
}

&-item-active,
&-submenu-active > &-submenu-title {
background-color: #eaf8fe;
}

&-item-selected {
background-color: #eaf8fe;
// fix chrome render bug
Expand All @@ -80,6 +75,38 @@
margin-top: 0;
}

.active-effect(@background-color) {
&:focus,
&:hover {
background-color: @background-color;
}
}

&-submenu {
&-title {
.active-effect(#eaf8fe);
}

&-open {
background-color: #eaf8fe;
}

&-disabled {
&-open {
background-color: transparent;
}
.active-effect(transparent);
}
}

&-item {
.active-effect(#eaf8fe);

&-disabled {
.active-effect(transparent);
}
}

&-item,
&-submenu-title {
margin: 0;
Expand Down
3 changes: 3 additions & 0 deletions docs/demo/performance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
## performance

<code src="../examples/performance.tsx">
53 changes: 53 additions & 0 deletions docs/examples/performance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import * as React from 'react'
import Menu from '../../src/Menu'
import SubMenu from '../../src/SubMenu'
import MenuItem from '../../src/MenuItem'
import type { MenuMode } from '../../src/interface'

const count = 50

const Performance = () => {
const [mode, setMode] = React.useState<MenuMode>('vertical')

return (
<div>
<div>
mode: <select
style={{ marginRight: 20 }}
value={mode}
onChange={e => setMode(e.target.value as MenuMode)}
>
<option value="inline">inline</option>
<option value="vertical">vertical</option>
<option value="horizontal">horizontal</option>
</select>
</div>

<div style={{ width: 200 }}>
<Menu
mode={mode}
defaultSelectedKeys={['0', '0 - 0']}
>
{new Array(count).fill(0).map((m, i) => {
const title = 'item - ' + i

return (
<SubMenu key={i} title={title}>
{new Array(count).fill(0).map((n, index) => {
const key = i + ' - ' + index
const subTitle = title + ' - ' + index

return (
<MenuItem key={key}>{subTitle}</MenuItem>
)
})}
</SubMenu>
)
})}
</Menu>
</div>
</div>
)
}

export default Performance
31 changes: 0 additions & 31 deletions src/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ export interface MenuProps
defaultOpenKeys?: string[];
openKeys?: string[];

// Active control
activeKey?: string;
defaultActiveFirst?: boolean;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

不能删除 API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

既然不能删除这两个 API 那我暂时想不到其他的方案,因为组件过多时确实是 node class 增删行为造成的卡顿。
不过可以通过这个 PR (#426),对 parseItems 方法进行缓存也能有效提升一倍的性能,可以复制以下代码进行测试:

// 在我的电脑,未使用 useMemo 缓存时, count = 130 会有明显卡顿,使用后 count = 260 才会有明显卡顿
const count = 260
export default () => (
  <div style={{ width: 200 }}>
    <Menu
      defaultSelectedKeys={['0', '0 - 0']}
    >
      {new Array(count).fill(0).map((m, i) => {
        const title = 'item - ' + i

        return (
          <SubMenu key={i} title={title}>
            {new Array(count).fill(0).map((n, index) => {
              const key = i + ' - ' + index
              const subTitle = title + ' - ' + index

              return (
                <MenuItem key={key}>{subTitle}</MenuItem>
              )
            })}
          </SubMenu>
        )
      })}
    </Menu>
  </div>
);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

嗯,现在提供了 items,准备下个大版本去掉语法糖的用法。解析 Node 太过昂贵,也缺少优化的空间。


// Selection
selectable?: boolean;
multiple?: boolean;
Expand Down Expand Up @@ -135,7 +131,6 @@ export interface MenuProps
stateProps: {
selected: boolean;
open: boolean;
active: boolean;
disabled: boolean;
},
) => React.ReactElement;
Expand Down Expand Up @@ -172,10 +167,6 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>((props, ref) => {
defaultOpenKeys,
openKeys,

// Active
activeKey,
defaultActiveFirst,

// Selection
selectable = true,
multiple = false,
Expand Down Expand Up @@ -328,22 +319,6 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>((props, ref) => {
);
}, [lastVisibleIndex, allVisible]);

// ======================== Active ========================
const [mergedActiveKey, setMergedActiveKey] = useMergedState(
activeKey || ((defaultActiveFirst && childList[0]?.key) as string),
{
value: activeKey,
},
);

const onActive = useMemoCallback((key: string) => {
setMergedActiveKey(key);
});

const onInactive = useMemoCallback(() => {
setMergedActiveKey(undefined);
});

// ======================== Select ========================
// >>>>> Select keys
const [mergedSelectKeys, setMergedSelectKeys] = useMergedState(
Expand Down Expand Up @@ -441,15 +416,13 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>((props, ref) => {

const onInternalKeyDown = useAccessibility(
mergedMode,
mergedActiveKey,
isRtl,
uuid,

containerRef,
getKeys,
getKeyPath,

setMergedActiveKey,
triggerAccessibilityOpen,

onKeyDown,
Expand Down Expand Up @@ -557,10 +530,6 @@ const Menu = React.forwardRef<HTMLUListElement, MenuProps>((props, ref) => {
// Motion
motion={mounted ? motion : null}
defaultMotions={mounted ? defaultMotions : null}
// Active
activeKey={mergedActiveKey}
onActive={onActive}
onInactive={onInactive}
// Selection
selectedKeys={mergedSelectKeys}
// Level
Expand Down
20 changes: 3 additions & 17 deletions src/MenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
RenderIconType,
} from './interface';
import { MenuContext } from './context/MenuContext';
import useActive from './hooks/useActive';
import useMouseEvents from './hooks/useMouseEvents';
import { warnItemProp } from './utils/warnUtil';
import Icon from './Icon';
import useDirectionStyle from './hooks/useDirectionStyle';
Expand Down Expand Up @@ -113,9 +113,6 @@ const InternalMenuItem = (props: MenuItemProps) => {

// Select
selectedKeys,

// Active
onActive,
} = React.useContext(MenuContext);

const { _internalRenderMenuItem } = React.useContext(PrivateContext);
Expand Down Expand Up @@ -150,7 +147,7 @@ const InternalMenuItem = (props: MenuItemProps) => {
const mergedItemIcon = itemIcon || contextItemIcon;

// ============================ Active ============================
const { active, ...activeProps } = useActive(
const mouseEvents = useMouseEvents(
eventKey,
mergedDisabled,
onMouseEnter,
Expand Down Expand Up @@ -187,15 +184,6 @@ const InternalMenuItem = (props: MenuItemProps) => {
}
};

/**
* Used for accessibility. Helper will focus element without key board.
* We should manually trigger an active
*/
const onInternalFocus: React.FocusEventHandler<HTMLLIElement> = e => {
onActive(eventKey);
onFocus?.(e);
};

// ============================ Render ============================
const optionRoleProps: React.HTMLAttributes<HTMLDivElement> = {};

Expand All @@ -211,7 +199,7 @@ const InternalMenuItem = (props: MenuItemProps) => {
tabIndex={disabled ? null : -1}
data-menu-id={overflowDisabled && domDataId ? null : domDataId}
{...restProps}
{...activeProps}
{...mouseEvents}
{...optionRoleProps}
component="li"
aria-disabled={disabled}
Expand All @@ -222,15 +210,13 @@ const InternalMenuItem = (props: MenuItemProps) => {
className={classNames(
itemCls,
{
[`${itemCls}-active`]: active,
[`${itemCls}-selected`]: selected,
[`${itemCls}-disabled`]: mergedDisabled,
},
className,
)}
onClick={onInternalClick}
onKeyDown={onInternalKeyDown}
onFocus={onInternalFocus}
>
{children}
<Icon
Expand Down
Loading