mirror of
https://github.com/ant-design/ant-design.git
synced 2025-06-07 17:44:35 +08:00
Add react-lazy-load for Transfer perfermance, close #2860
This commit is contained in:
parent
6a1b1476be
commit
7373ce0758
64
components/transfer/demo/large-data.md
Normal file
64
components/transfer/demo/large-data.md
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
order: 4
|
||||||
|
debug: true
|
||||||
|
title:
|
||||||
|
zh-CN: 大数据性能测试
|
||||||
|
en-US: Performance Test
|
||||||
|
---
|
||||||
|
|
||||||
|
## zh-CN
|
||||||
|
|
||||||
|
2000 条数据。
|
||||||
|
|
||||||
|
## en-US
|
||||||
|
|
||||||
|
2000 items.
|
||||||
|
|
||||||
|
````jsx
|
||||||
|
import { Transfer } from 'antd';
|
||||||
|
|
||||||
|
const App = React.createClass({
|
||||||
|
getInitialState() {
|
||||||
|
return {
|
||||||
|
mockData: [],
|
||||||
|
targetKeys: [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
componentDidMount() {
|
||||||
|
this.getMock();
|
||||||
|
},
|
||||||
|
getMock() {
|
||||||
|
const targetKeys = [];
|
||||||
|
const mockData = [];
|
||||||
|
for (let i = 0; i < 2000; i++) {
|
||||||
|
const data = {
|
||||||
|
key: i.toString(),
|
||||||
|
title: `content${i + 1}`,
|
||||||
|
description: `description of content${i + 1}`,
|
||||||
|
chosen: Math.random() * 2 > 1,
|
||||||
|
};
|
||||||
|
if (data.chosen) {
|
||||||
|
targetKeys.push(data.key);
|
||||||
|
}
|
||||||
|
mockData.push(data);
|
||||||
|
}
|
||||||
|
this.setState({ mockData, targetKeys });
|
||||||
|
},
|
||||||
|
handleChange(targetKeys, direction, moveKeys) {
|
||||||
|
console.log(targetKeys, direction, moveKeys);
|
||||||
|
this.setState({ targetKeys });
|
||||||
|
},
|
||||||
|
render() {
|
||||||
|
return (
|
||||||
|
<Transfer
|
||||||
|
dataSource={this.state.mockData}
|
||||||
|
targetKeys={this.state.targetKeys}
|
||||||
|
onChange={this.handleChange}
|
||||||
|
render={item => item.title}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
ReactDOM.render(<App />, mountNode);
|
||||||
|
````
|
@ -15,7 +15,6 @@ To transfer the elements between two columns in an intuitive and efficient way.
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
|
||||||
| Property | Description | Type | Default |
|
| Property | Description | Type | Default |
|
||||||
|-----------|------------------------------------------|------------|--------|
|
|-----------|------------------------------------------|------------|--------|
|
||||||
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop. | Array | [] |
|
| dataSource | Used for setting the source data. The elements that are part of this array will be present the left column. Except the elements whose keys are included in `targetKeys` prop. | Array | [] |
|
||||||
@ -31,11 +30,11 @@ To transfer the elements between two columns in an intuitive and efficient way.
|
|||||||
| searchPlaceholder | The hint text of the search box. | String | 'Search here' |
|
| searchPlaceholder | The hint text of the search box. | String | 'Search here' |
|
||||||
| notFoundContent | Text to display when a column is empty. | React.node | 'The list is empty' |
|
| notFoundContent | Text to display when a column is empty. | React.node | 'The list is empty' |
|
||||||
| footer | A function used for rendering the footer. | Function(props) | |
|
| footer | A function used for rendering the footer. | Function(props) | |
|
||||||
|
| lazy | property of [react-lazy-load](https://github.com/loktar00/react-lazy-load) for lazy rendering items | Object | `{ height: 32, offset: 32 }` |
|
||||||
|
|
||||||
## Warning
|
## Warning
|
||||||
|
|
||||||
According the [standard](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children) of React, the key should always be supplied directly to the elements in the array. In Transfer, the keys should be set on the elements included in `dataSource` array. By default, `key` property is used as an unique identifier.
|
According the [standard](http://facebook.github.io/react/docs/multiple-components.html#dynamic-children) of React, the key should always be supplied directly to the elements in the array. In Transfer, the keys should be set on the elements included in `dataSource` array. By default, `key` property is used as an unique identifier.
|
||||||
|
|
||||||
If there's no `key` in your data, you should use `rowKey` to specify the key that will be used for uniquely identify each element.
|
If there's no `key` in your data, you should use `rowKey` to specify the key that will be used for uniquely identify each element.
|
||||||
```jsx
|
```jsx
|
||||||
|
@ -35,6 +35,7 @@ export interface TransferProps {
|
|||||||
filterOption: (inputValue: any, item: any) => boolean;
|
filterOption: (inputValue: any, item: any) => boolean;
|
||||||
body?: (props: any) => any;
|
body?: (props: any) => any;
|
||||||
rowKey?: (record: any) => string;
|
rowKey?: (record: any) => string;
|
||||||
|
lazy?: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransferContext {
|
export interface TransferContext {
|
||||||
@ -73,6 +74,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
body: PropTypes.func,
|
body: PropTypes.func,
|
||||||
footer: PropTypes.func,
|
footer: PropTypes.func,
|
||||||
rowKey: PropTypes.func,
|
rowKey: PropTypes.func,
|
||||||
|
lazy: PropTypes.object,
|
||||||
};
|
};
|
||||||
|
|
||||||
static contextTypes = {
|
static contextTypes = {
|
||||||
@ -255,7 +257,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
const {
|
const {
|
||||||
prefixCls = 'ant-transfer', operations = [], showSearch, notFoundContent,
|
prefixCls = 'ant-transfer', operations = [], showSearch, notFoundContent,
|
||||||
searchPlaceholder, body, footer, listStyle, className = '',
|
searchPlaceholder, body, footer, listStyle, className = '',
|
||||||
filterOption, render,
|
filterOption, render, lazy,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
|
const { leftFilter, rightFilter, leftCheckedKeys, rightCheckedKeys } = this.state;
|
||||||
|
|
||||||
@ -271,7 +273,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
const titles = this.getTitles();
|
const titles = this.getTitles();
|
||||||
return (
|
return (
|
||||||
<div className={cls}>
|
<div className={cls}>
|
||||||
<List titleText={titles[0]}
|
<List
|
||||||
|
titleText={titles[0]}
|
||||||
dataSource={leftDataSource}
|
dataSource={leftDataSource}
|
||||||
filter={leftFilter}
|
filter={leftFilter}
|
||||||
filterOption={filterOption}
|
filterOption={filterOption}
|
||||||
@ -288,8 +291,10 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
body={body}
|
body={body}
|
||||||
footer={footer}
|
footer={footer}
|
||||||
prefixCls={`${prefixCls}-list`}
|
prefixCls={`${prefixCls}-list`}
|
||||||
|
lazy={lazy}
|
||||||
/>
|
/>
|
||||||
<Operation rightActive={rightActive}
|
<Operation
|
||||||
|
rightActive={rightActive}
|
||||||
rightArrowText={operations[0]}
|
rightArrowText={operations[0]}
|
||||||
moveToRight={this.moveToRight}
|
moveToRight={this.moveToRight}
|
||||||
leftActive={leftActive}
|
leftActive={leftActive}
|
||||||
@ -297,7 +302,8 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
moveToLeft={this.moveToLeft}
|
moveToLeft={this.moveToLeft}
|
||||||
className={`${prefixCls}-operation`}
|
className={`${prefixCls}-operation`}
|
||||||
/>
|
/>
|
||||||
<List titleText={titles[1]}
|
<List
|
||||||
|
titleText={titles[1]}
|
||||||
dataSource={rightDataSource}
|
dataSource={rightDataSource}
|
||||||
filter={rightFilter}
|
filter={rightFilter}
|
||||||
filterOption={filterOption}
|
filterOption={filterOption}
|
||||||
@ -314,6 +320,7 @@ export default class Transfer extends React.Component<TransferProps, any> {
|
|||||||
body={body}
|
body={body}
|
||||||
footer={footer}
|
footer={footer}
|
||||||
prefixCls={`${prefixCls}-list`}
|
prefixCls={`${prefixCls}-list`}
|
||||||
|
lazy={lazy}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -16,7 +16,6 @@ title: Transfer
|
|||||||
|
|
||||||
## API
|
## API
|
||||||
|
|
||||||
|
|
||||||
| 参数 | 说明 | 类型 | 默认值 |
|
| 参数 | 说明 | 类型 | 默认值 |
|
||||||
|-----------|------------------------------------------|------------|--------|
|
|-----------|------------------------------------------|------------|--------|
|
||||||
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外。 | Array | [] |
|
| dataSource | 数据源,其中的数据将会被渲染到左边一栏中,`targetKeys` 中指定的除外。 | Array | [] |
|
||||||
@ -33,7 +32,7 @@ title: Transfer
|
|||||||
| searchPlaceholder | 搜索框的默认值 | String | '请输入搜索内容' |
|
| searchPlaceholder | 搜索框的默认值 | String | '请输入搜索内容' |
|
||||||
| notFoundContent | 当列表为空时显示的内容 | React.node | '列表为空' |
|
| notFoundContent | 当列表为空时显示的内容 | React.node | '列表为空' |
|
||||||
| footer | 底部渲染函数 | Function(props) | |
|
| footer | 底部渲染函数 | Function(props) | |
|
||||||
|
| lazy | Transfer 使用了 [react-lazy-load](https://github.com/loktar00/react-lazy-load) 优化性能,这里可以设置相关参数 | Object | `{ height: 32, offset: 32 }` |
|
||||||
|
|
||||||
## 注意
|
## 注意
|
||||||
|
|
||||||
|
@ -5,6 +5,7 @@ import classNames from 'classnames';
|
|||||||
import Animate from 'rc-animate';
|
import Animate from 'rc-animate';
|
||||||
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
import PureRenderMixin from 'rc-util/lib/PureRenderMixin';
|
||||||
import assign from 'object-assign';
|
import assign from 'object-assign';
|
||||||
|
import Lazyload from 'react-lazy-load';
|
||||||
import { TransferItem } from './index';
|
import { TransferItem } from './index';
|
||||||
|
|
||||||
function noop() {
|
function noop() {
|
||||||
@ -35,6 +36,7 @@ export interface TransferListProps {
|
|||||||
position?: string;
|
position?: string;
|
||||||
notFoundContent?: React.ReactNode | string;
|
notFoundContent?: React.ReactNode | string;
|
||||||
filterOption: (filterText: any, item: any) => boolean;
|
filterOption: (filterText: any, item: any) => boolean;
|
||||||
|
lazy?: {};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TransferListContext {
|
export interface TransferListContext {
|
||||||
@ -135,7 +137,7 @@ export default class TransferList extends React.Component<TransferListProps, any
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { prefixCls, dataSource, titleText, filter, checkedKeys,
|
const { prefixCls, dataSource, titleText, filter, checkedKeys, lazy,
|
||||||
body = noop, footer = noop, showSearch, render = noop, style } = this.props;
|
body = noop, footer = noop, showSearch, render = noop, style } = this.props;
|
||||||
|
|
||||||
let { searchPlaceholder, notFoundContent } = this.props;
|
let { searchPlaceholder, notFoundContent } = this.props;
|
||||||
@ -177,16 +179,22 @@ export default class TransferList extends React.Component<TransferListProps, any
|
|||||||
[`${prefixCls}-content-item`]: true,
|
[`${prefixCls}-content-item`]: true,
|
||||||
[`${prefixCls}-content-item-disabled`]: item.disabled,
|
[`${prefixCls}-content-item-disabled`]: item.disabled,
|
||||||
});
|
});
|
||||||
|
const lazyProps = assign({
|
||||||
|
height: 32,
|
||||||
|
offset: 320,
|
||||||
|
}, lazy);
|
||||||
return (
|
return (
|
||||||
<li
|
<Lazyload key={item.key} {...lazyProps}>
|
||||||
key={item.key}
|
<li
|
||||||
className={className}
|
key={item.key}
|
||||||
title={renderedText}
|
className={className}
|
||||||
onClick={item.disabled ? undefined : () => this.handleSelect(item)}
|
title={renderedText}
|
||||||
>
|
onClick={item.disabled ? undefined : () => this.handleSelect(item)}
|
||||||
<Checkbox checked={checkedKeys.some(key => key === item.key)} disabled={item.disabled} />
|
>
|
||||||
<span>{renderedEl}</span>
|
<Checkbox checked={checkedKeys.some(key => key === item.key)} disabled={item.disabled} />
|
||||||
</li>
|
<span>{renderedEl}</span>
|
||||||
|
</li>
|
||||||
|
</Lazyload>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -98,6 +98,7 @@
|
|||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
padding: 7px 15px;
|
padding: 7px 15px;
|
||||||
|
min-height: 32px;
|
||||||
transition: all 0.3s ease;
|
transition: all 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
"rc-tree-select": "~1.8.0",
|
"rc-tree-select": "~1.8.0",
|
||||||
"rc-upload": "~2.2.0",
|
"rc-upload": "~2.2.0",
|
||||||
"rc-util": "^4.0.1",
|
"rc-util": "^4.0.1",
|
||||||
|
"react-lazy-load": "^3.0.10",
|
||||||
"react-slick": "~0.14.2",
|
"react-slick": "~0.14.2",
|
||||||
"shallowequal": "^0.2.2",
|
"shallowequal": "^0.2.2",
|
||||||
"warning": "~3.0.0"
|
"warning": "~3.0.0"
|
||||||
|
2
typings/custom-typings.d.ts
vendored
2
typings/custom-typings.d.ts
vendored
@ -76,6 +76,8 @@ declare module 'rc-collapse';
|
|||||||
|
|
||||||
declare module 'rc-form*';
|
declare module 'rc-form*';
|
||||||
|
|
||||||
|
declare module 'react-lazy-load';
|
||||||
|
|
||||||
declare var process: {
|
declare var process: {
|
||||||
env: {
|
env: {
|
||||||
NODE_ENV: string
|
NODE_ENV: string
|
||||||
|
Loading…
Reference in New Issue
Block a user