Add react-lazy-load for Transfer perfermance, close #2860

This commit is contained in:
afc163 2016-11-03 16:05:59 +08:00
parent 6a1b1476be
commit 7373ce0758
8 changed files with 100 additions and 19 deletions

View 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);
````

View File

@ -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

View File

@ -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>
); );

View File

@ -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 }` |
## 注意 ## 注意

View File

@ -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>
); );
}); });

View File

@ -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;
} }

View File

@ -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"

View File

@ -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