Browse Source

refactor: opt for typography Tooltip perf (#33669)

pull/33680/head
二货机器人 3 years ago
committed by GitHub
parent
commit
18296d1c46
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 95
      components/typography/Base.tsx
  2. 19
      components/typography/__tests__/index.test.js
  3. 2
      package.json

95
components/typography/Base.tsx

@ -3,6 +3,7 @@ import classNames from 'classnames';
import toArray from 'rc-util/lib/Children/toArray';
import copy from 'copy-to-clipboard';
import omit from 'rc-util/lib/omit';
import { composeRef } from 'rc-util/lib/ref';
import EditOutlined from '@ant-design/icons/EditOutlined';
import CheckOutlined from '@ant-design/icons/CheckOutlined';
import CopyOutlined from '@ant-design/icons/CopyOutlined';
@ -112,6 +113,7 @@ interface BaseState {
ellipsisText: string;
ellipsisContent: React.ReactNode;
isEllipsis: boolean;
isNativeEllipsis: boolean;
expanded: boolean;
clientRendered: boolean;
}
@ -169,6 +171,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
ellipsisText: '',
ellipsisContent: null,
isEllipsis: false,
isNativeEllipsis: false,
expanded: false,
clientRendered: false,
};
@ -180,11 +183,25 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
componentDidUpdate(prevProps: BlockProps) {
const { children } = this.props;
const { isNativeEllipsis } = this.state;
const ellipsis = this.getEllipsis();
const prevEllipsis = this.getEllipsis(prevProps);
if (children !== prevProps.children || ellipsis.rows !== prevEllipsis.rows) {
this.resizeOnNextFrame();
}
// If use native ellipsis, we should check if ellipsis changed
const textEle = this.contentRef.current;
if (this.canUseCSSEllipsis() && textEle) {
const currentEllipsis = textEle.offsetWidth < textEle.scrollWidth;
if (isNativeEllipsis !== currentEllipsis) {
// eslint-disable-next-line react/no-did-update-set-state
this.setState({
isNativeEllipsis: currentEllipsis,
});
}
}
}
componentWillUnmount() {
@ -297,9 +314,9 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
canUseCSSEllipsis(): boolean {
const { clientRendered } = this.state;
const { editable, copyable } = this.props;
const { rows, expandable, suffix, onEllipsis, tooltip } = this.getEllipsis();
const { rows, expandable, suffix, onEllipsis } = this.getEllipsis();
if (suffix || tooltip) return false;
if (suffix) return false;
// Can't use css ellipsis since we need to provide the place for button
if (editable || copyable || expandable || !clientRendered || onEllipsis) {
return false;
@ -458,7 +475,7 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
}
renderContent() {
const { ellipsisContent, isEllipsis, expanded } = this.state;
const { ellipsisContent, isEllipsis, isNativeEllipsis, expanded } = this.state;
const { component, children, className, type, disabled, style, ...restProps } = this.props;
const { direction } = this.context;
const { rows, suffix, tooltip } = this.getEllipsis();
@ -508,15 +525,6 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
{suffix}
</>
);
// If provided tooltip, we need wrap with span to let Tooltip inject events
if (tooltip) {
textNode = (
<Tooltip title={tooltip === true ? children : tooltip}>
<span>{textNode}</span>
</Tooltip>
);
}
} else {
textNode = (
<>
@ -538,31 +546,44 @@ class Base extends React.Component<InternalBlockProps, BaseState> {
return (
<ResizeObserver onResize={this.resizeOnNextFrame} disabled={cssEllipsis}>
<Typography
className={classNames(
{
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-ellipsis`]: rows,
[`${prefixCls}-single-line`]: rows === 1 && !isEllipsis,
[`${prefixCls}-ellipsis-single-line`]: cssTextOverflow,
[`${prefixCls}-ellipsis-multiple-line`]: cssLineClamp,
},
className,
)}
style={{
...style,
WebkitLineClamp: cssLineClamp ? rows : undefined,
}}
component={component}
ref={this.contentRef}
direction={direction}
onClick={triggerType.indexOf('text') !== -1 ? this.onEditClick : () => {}}
{...textProps}
>
{textNode}
{this.renderOperations()}
</Typography>
{resizeRef => {
let typography = (
<Typography
className={classNames(
{
[`${prefixCls}-${type}`]: type,
[`${prefixCls}-disabled`]: disabled,
[`${prefixCls}-ellipsis`]: rows,
[`${prefixCls}-single-line`]: rows === 1 && !isEllipsis,
[`${prefixCls}-ellipsis-single-line`]: cssTextOverflow,
[`${prefixCls}-ellipsis-multiple-line`]: cssLineClamp,
},
className,
)}
style={{
...style,
WebkitLineClamp: cssLineClamp ? rows : undefined,
}}
component={component}
ref={composeRef(this.contentRef, resizeRef)}
direction={direction}
onClick={triggerType.indexOf('text') !== -1 ? this.onEditClick : () => {}}
{...textProps}
>
{textNode}
{this.renderOperations()}
</Typography>
);
// If provided tooltip, we need wrap with span to let Tooltip inject events
if (cssEllipsis ? isNativeEllipsis : isEllipsis) {
typography = (
<Tooltip title={tooltip === true ? children : tooltip}>{typography}</Tooltip>
);
}
return typography;
}}
</ResizeObserver>
);
}}

19
components/typography/__tests__/index.test.js

@ -3,7 +3,7 @@ import { mount } from 'enzyme';
import { SmileOutlined, LikeOutlined, HighlightOutlined, CheckOutlined } from '@ant-design/icons';
import KeyCode from 'rc-util/lib/KeyCode';
import { resetWarned } from 'rc-util/lib/warning';
import { spyElementPrototype } from 'rc-util/lib/test/domHook';
import { spyElementPrototype, spyElementPrototypes } from 'rc-util/lib/test/domHook';
import copy from 'copy-to-clipboard';
import Title from '../Title';
import Link from '../Link';
@ -258,6 +258,23 @@ describe('Typography', () => {
});
describe('should tooltip support', () => {
let domSpy;
beforeAll(() => {
domSpy = spyElementPrototypes(HTMLElement, {
offsetWidth: {
get: () => 100,
},
scrollWidth: {
get: () => 200,
},
});
});
afterAll(() => {
domSpy.mockRestore();
});
function getWrapper(tooltip) {
return mount(
<Base ellipsis={{ tooltip }} component="p">

2
package.json

@ -138,7 +138,7 @@
"rc-picker": "~2.5.17",
"rc-progress": "~3.2.1",
"rc-rate": "~2.9.0",
"rc-resize-observer": "^1.1.2",
"rc-resize-observer": "^1.2.0",
"rc-select": "~14.0.0-alpha.15",
"rc-slider": "~9.7.4",
"rc-steps": "~4.1.0",

Loading…
Cancel
Save