Skip to content
Merged
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
4 changes: 4 additions & 0 deletions docs/demo.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,7 @@ Option has `key` and filter only hit by `key`
## Allow Clear

<code src="./examples/allowClear.tsx"></code>

## On Scroll

<code src="./examples/onScroll.tsx"></code>
3 changes: 3 additions & 0 deletions docs/examples/debug.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ export default () => (
<Mentions
rows={3}
defaultValue="Hello @ World @"
onScroll={e => {
console.log(e);
}}
open
options={[
{
Expand Down
4 changes: 4 additions & 0 deletions docs/examples/onScroll.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.on-scroll .rc-mentions-dropdown-menu {
max-height: 250px;
overflow: auto;
}
18 changes: 18 additions & 0 deletions docs/examples/onScroll.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import React from 'react';
import Mentions from 'rc-mentions';
import '../../assets/index.less';
import './onScroll.less';

export default () => (
<Mentions
rows={3}
defaultValue="Hello @ World @"
onPopupScroll={console.log}
dropdownClassName="on-scroll"
open
options={Array.from({ length: 1000 }).map((_, index) => ({
value: `item-${index}`,
label: `item-${index}`,
}))}
Comment on lines +13 to +16
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

建议优化下拉列表的性能

创建1000个选项可能会导致性能问题。建议:

  1. 考虑使用虚拟滚动来优化长列表的渲染
  2. 实现分页加载而不是一次性加载所有选项

建议重构为以下实现:

-    options={Array.from({ length: 1000 }).map((_, index) => ({
-      value: `item-${index}`,
-      label: `item-${index}`,
-    }))}
+    options={Array.from({ length: 50 }).map((_, index) => ({
+      value: `item-${index}`,
+      label: `item-${index}`,
+    }))}
+    onDropdownScroll={(e) => {
+      // 实现滚动加载更多选项的逻辑
+    }}

Committable suggestion skipped: line range outside the PR's diff.

/>
);
2 changes: 2 additions & 0 deletions src/DropdownMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ function DropdownMenu(props: DropdownMenuProps) {
selectOption,
onFocus,
onBlur,
onScroll,
} = React.useContext(MentionsContext);

const { prefixCls, options } = props;
Expand All @@ -34,6 +35,7 @@ function DropdownMenu(props: DropdownMenuProps) {
}}
onFocus={onFocus}
onBlur={onBlur}
onScroll={onScroll}
>
{options.map((option, index) => {
const { key, disabled, className, style, label } = option;
Expand Down
13 changes: 12 additions & 1 deletion src/Mentions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export interface MentionsProps extends BaseTextareaAttrs {
classNames?: CommonInputProps['classNames'] & {
mentions?: string;
};
onPopupScroll?: (event: React.UIEvent<HTMLDivElement>) => void;
}

export interface MentionsRef {
Expand Down Expand Up @@ -130,6 +131,8 @@ const InternalMentions = forwardRef<MentionsRef, MentionsProps>(
// https://github.com/ant-design/ant-design/blob/df933e94efc8f376003bbdc658d64b64a0e53495/components/mentions/demo/render-panel.tsx
// @ts-expect-error
visible,
onPopupScroll,

// Rest
...restProps
} = props;
Expand Down Expand Up @@ -397,7 +400,6 @@ const InternalMentions = forwardRef<MentionsRef, MentionsProps>(
key === 'Shift' ||
which === KeyCode.ALT ||
key === 'AltGraph' ||

mergedMeasuring ||
(nextMeasureText !== mergedMeasureText && matchOption)
) {
Expand Down Expand Up @@ -455,7 +457,15 @@ const InternalMentions = forwardRef<MentionsRef, MentionsProps>(
onInternalBlur();
};

// ============================== Scroll ===============================
const onInternalPopupScroll: React.UIEventHandler<
HTMLDivElement
> = event => {
onPopupScroll?.(event);
};

// ============================== Render ==============================

return (
<div
className={classNames(prefixCls, className)}
Expand Down Expand Up @@ -485,6 +495,7 @@ const InternalMentions = forwardRef<MentionsRef, MentionsProps>(
selectOption,
onFocus: onDropdownFocus,
onBlur: onDropdownBlur,
onScroll: onInternalPopupScroll,
}}
>
<KeywordTrigger
Expand Down
1 change: 1 addition & 0 deletions src/MentionsContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export interface MentionsContextProps {
selectOption: (option: OptionProps) => void;
onFocus: React.FocusEventHandler<HTMLElement>;
onBlur: React.FocusEventHandler<HTMLElement>;
onScroll: React.UIEventHandler<HTMLElement>;
}

// We will never use default, here only to fix TypeScript warning
Expand Down
11 changes: 11 additions & 0 deletions tests/Mentions.spec.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,17 @@ describe('Mentions', () => {
expect(container.firstChild).toHaveClass('rc-mentions-disabled');
});

it('onPopupScroll should work', () => {
const onPopupScroll = jest.fn();
const { container, baseElement } = renderMentions({ onPopupScroll });
simulateInput(container, '@');
act(() => {
jest.runAllTimers();
});
fireEvent.scroll(baseElement.querySelector('.rc-mentions-dropdown-menu'));
expect(onPopupScroll).toHaveBeenCalled();
});

describe('nativeElement', () => {
it('work', () => {
const ref = createRef<MentionsRef>();
Expand Down