mirror of
https://github.com/ant-design/ant-design.git
synced 2025-01-18 22:36:31 +08:00
List virtualized (#7692)
* add virtualized & infinite demo * change `children render` to `renderItem`
This commit is contained in:
parent
ca06211494
commit
91b97d7b25
@ -12,7 +12,6 @@ export interface ListItemProps {
|
||||
extra: React.ReactNode;
|
||||
actions?: Array<React.ReactNode>;
|
||||
grid?: ListGridType;
|
||||
Meta: React.ReactNode;
|
||||
}
|
||||
|
||||
export interface ListItemMetaProps {
|
||||
|
@ -31,7 +31,7 @@ exports[`renders ./components/list/demo/basic.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 1
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -94,7 +94,7 @@ exports[`renders ./components/list/demo/basic.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 2
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -157,7 +157,7 @@ exports[`renders ./components/list/demo/basic.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 3
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -220,7 +220,7 @@ exports[`renders ./components/list/demo/basic.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 4
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -258,14 +258,14 @@ exports[`renders ./components/list/demo/basic.md correctly 1`] = `
|
||||
</ul>
|
||||
</div>
|
||||
<div
|
||||
class="ant-list-more"
|
||||
style="text-align:center;margin-top:8px;"
|
||||
>
|
||||
<button
|
||||
class="ant-btn"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
加载更多...
|
||||
加载更多
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
@ -305,7 +305,7 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -344,7 +344,7 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -383,7 +383,7 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -422,85 +422,7 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -522,210 +444,31 @@ exports[`renders ./components/list/demo/grid.md correctly 1`] = `
|
||||
`;
|
||||
|
||||
exports[`renders ./components/list/demo/infinite-load.md correctly 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="ant-list ant-list-bordered"
|
||||
>
|
||||
<div />
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`renders ./components/list/demo/infinite-virtualized-load.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-list ant-list-bordered ant-list-grid ant-list-infinite"
|
||||
class="ant-list ant-list-bordered"
|
||||
>
|
||||
<div>
|
||||
<div />
|
||||
<div
|
||||
style="overflow:visible;width:0;"
|
||||
>
|
||||
<div
|
||||
class="ant-row"
|
||||
style="margin-left:-8px;margin-right:-8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
List Item Title 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
List Item Content 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
List Item Title 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
List Item Content 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
List Item Title 3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
List Item Content 3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
List Item Title 4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
List Item Content 4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-6"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
List Item Title 5
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
List Item Content 5
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
aria-label="grid"
|
||||
aria-readonly="true"
|
||||
class="ReactVirtualized__Grid ReactVirtualized__List"
|
||||
role="grid"
|
||||
style="box-sizing:border-box;direction:ltr;height:auto;position:relative;width:0;-webkit-overflow-scrolling:touch;will-change:transform;overflow-x:hidden;overflow-y:hidden;"
|
||||
tabindex="0"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
@ -761,7 +504,7 @@ exports[`renders ./components/list/demo/meta.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 1
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -801,7 +544,7 @@ exports[`renders ./components/list/demo/meta.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 2
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -841,7 +584,7 @@ exports[`renders ./components/list/demo/meta.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 3
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -881,7 +624,7 @@ exports[`renders ./components/list/demo/meta.md correctly 1`] = `
|
||||
<a
|
||||
href="https://ant.design"
|
||||
>
|
||||
Ant design
|
||||
Ant Design Title 4
|
||||
</a>
|
||||
</h4>
|
||||
<div
|
||||
@ -931,7 +674,7 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 1
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -970,7 +713,7 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 2
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1009,7 +752,7 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 3
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -1048,85 +791,7 @@ exports[`renders ./components/list/demo/resposive.md correctly 1`] = `
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-12 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-card-body"
|
||||
>
|
||||
<div>
|
||||
Card content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="ant-col-xs-12 ant-col-sm-12 ant-col-md-6 ant-col-lg-6 ant-col-xl-4"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item"
|
||||
style="padding-left:8px;padding-right:8px;"
|
||||
>
|
||||
<div
|
||||
class="ant-list-item-content ant-list-item-content-single"
|
||||
>
|
||||
<div
|
||||
class="ant-card ant-card-bordered"
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
class="ant-card-head"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-wrapper"
|
||||
>
|
||||
<div
|
||||
class="ant-card-head-title"
|
||||
>
|
||||
Card title
|
||||
Title 4
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -14,46 +14,62 @@ title:
|
||||
Basic List.
|
||||
|
||||
````jsx
|
||||
import { List, Avatar } from 'antd';
|
||||
import { List, Avatar, Button, Icon } from 'antd';
|
||||
|
||||
ReactDOM.render(
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
showLoadMore
|
||||
onLoadMore={() => {}}
|
||||
>
|
||||
<List.Item actions={[<a>编辑</a>, <a>更多</a>]}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
const data = [
|
||||
{
|
||||
title: 'Ant Design Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 4',
|
||||
},
|
||||
];
|
||||
|
||||
class BasicList extends React.Component {
|
||||
state = {
|
||||
loadingMore: false,
|
||||
showLoadingMore: true,
|
||||
}
|
||||
onLoadMore = () => {
|
||||
this.setState({
|
||||
loadingMore: true,
|
||||
});
|
||||
}
|
||||
render() {
|
||||
const { loadingMore, showLoadingMore } = this.state;
|
||||
const loadMore = showLoadingMore ? (
|
||||
<div style={{ textAlign: 'center', marginTop: 8 }}>
|
||||
<Button onClick={this.onLoadMore}>
|
||||
{loadingMore && (<span><Icon type="loading" /> 加载中...</span>)}
|
||||
{!loadingMore && (<span>加载更多</span>)}
|
||||
</Button>
|
||||
</div>
|
||||
) : null;
|
||||
return (
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
loadMore={loadMore}
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item actions={[<a>编辑</a>, <a>更多</a>]}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">{item.title}</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
<List.Item actions={[<a>编辑</a>, <a>更多</a>]}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
<List.Item actions={[<a>编辑</a>, <a>更多</a>]}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
<List.Item actions={[<a>编辑</a>, <a>更多</a>]}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
</List>
|
||||
, mountNode);
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<BasicList />, mountNode);
|
||||
````
|
||||
|
@ -16,28 +16,30 @@ Grid List.
|
||||
````jsx
|
||||
import { List, Card } from 'antd';
|
||||
|
||||
const data = [
|
||||
{
|
||||
title: 'Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Title 4',
|
||||
},
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<List
|
||||
grid={{ gutter: 16, column: 4 }}
|
||||
>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
</List>
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item>
|
||||
<Card title={item.title}>Card content</Card>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -1,83 +1,97 @@
|
||||
---
|
||||
order: 6
|
||||
order: 7
|
||||
title:
|
||||
zh-CN: 无限加载
|
||||
en-US: infinite load
|
||||
zh-CN: 滚动加载
|
||||
en-US: Scrolling loaded List
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
无限加载样例。
|
||||
结合 [react-infinite-scroller](https://github.com/CassetteRocks/react-infinite-scroller) 实现滚动自动加载列表。
|
||||
|
||||
## en-US
|
||||
|
||||
The example of infinite load.
|
||||
The example of infinite load with [react-infinite-scroller](https://github.com/CassetteRocks/react-infinite-scroller).
|
||||
|
||||
````jsx
|
||||
import { List, Card, message } from 'antd';
|
||||
import { List, message, Avatar, Spin } from 'antd';
|
||||
import reqwest from 'reqwest';
|
||||
|
||||
let countId = 1;
|
||||
import InfiniteScroll from 'react-infinite-scroller';
|
||||
|
||||
function mockData() {
|
||||
const data = [];
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const id = countId;
|
||||
data.push({
|
||||
id: `id-${id}`,
|
||||
title: `List Item Title ${id}`,
|
||||
content: `List Item Content ${id}`,
|
||||
});
|
||||
countId++;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
const fakeDataUrl = 'https://randomapi.com/api/dleyg4om?key=Z51U-D9OX-SXIO-SLJ9&fmt=raw&sole';
|
||||
|
||||
class InfiniteList extends React.Component {
|
||||
class InfiniteListExample extends React.Component {
|
||||
state = {
|
||||
data: mockData(),
|
||||
data: [],
|
||||
loading: false,
|
||||
hasMore: true,
|
||||
}
|
||||
handleInfiniteOnLoad = (done) => {
|
||||
getData = (callback) => {
|
||||
reqwest({
|
||||
url: fakeDataUrl,
|
||||
type: 'json',
|
||||
method: 'get',
|
||||
contentType: 'application/json',
|
||||
success: (res) => {
|
||||
callback(res);
|
||||
},
|
||||
});
|
||||
}
|
||||
componentWillMount() {
|
||||
this.getData((res) => {
|
||||
this.setState({
|
||||
data: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
handleInfiniteOnLoad = () => {
|
||||
let data = this.state.data;
|
||||
if (data.length > 15) {
|
||||
message.warning('Loaded All');
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
loading: true,
|
||||
});
|
||||
setTimeout(() => {
|
||||
data = data.concat(mockData());
|
||||
if (data.length > 14) {
|
||||
message.warning('Infinite List loaded all');
|
||||
this.setState({
|
||||
hasMore: false,
|
||||
loading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.getData((res) => {
|
||||
data = data.concat(res);
|
||||
this.setState({
|
||||
data,
|
||||
loading: false,
|
||||
});
|
||||
// reset the infinite onLoad callback flag
|
||||
// so can trigger onLoad callback again
|
||||
done();
|
||||
}, 1000);
|
||||
});
|
||||
}
|
||||
render() {
|
||||
return (
|
||||
<List
|
||||
infinite={{
|
||||
loading: this.state.loading,
|
||||
onLoad: this.handleInfiniteOnLoad,
|
||||
offset: -20,
|
||||
}}
|
||||
grid={{ gutter: 16, column: 4 }}
|
||||
<InfiniteScroll
|
||||
pageStart={0}
|
||||
loadMore={this.handleInfiniteOnLoad}
|
||||
hasMore={!this.state.loading && this.state.hasMore}
|
||||
>
|
||||
{
|
||||
this.state.data.map(item => (
|
||||
<List
|
||||
dataSource={this.state.data}
|
||||
renderItem={item => (
|
||||
<List.Item key={item.id}>
|
||||
<Card title={item.title}>{item.content}</Card>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">{item.title}</a>}
|
||||
description={item.content}
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
))
|
||||
}
|
||||
</List>
|
||||
)}
|
||||
>
|
||||
{this.state.loading && this.state.hasMore && <Spin style={{ position: 'absolute', bottom: 0, left: '50%' }} />}
|
||||
</List>
|
||||
</InfiniteScroll>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<InfiniteList />, mountNode);
|
||||
````
|
||||
ReactDOM.render(<InfiniteListExample />, mountNode);
|
||||
````
|
136
components/list/demo/infinite-virtualized-load.md
Normal file
136
components/list/demo/infinite-virtualized-load.md
Normal file
@ -0,0 +1,136 @@
|
||||
---
|
||||
order: 6
|
||||
title:
|
||||
zh-CN: 滚动加载无限长列表
|
||||
en-US: Infinite virtualized List
|
||||
---
|
||||
|
||||
## zh-CN
|
||||
|
||||
结合 [react-virtualized](https://github.com/bvaughn/react-virtualized) 实现滚动加载无限长列表,带有虚拟化([virtualization](https://blog.jscrambler.com/optimizing-react-rendering-through-virtualization/))功能,能够提高数据量大时候长列表的性能。
|
||||
|
||||
## en-US
|
||||
|
||||
The example of infinite & virtualized load with [react-virtualized](https://github.com/bvaughn/react-virtualized).
|
||||
|
||||
````jsx
|
||||
import { List, message, Avatar, Spin } from 'antd';
|
||||
|
||||
import reqwest from 'reqwest';
|
||||
|
||||
import WindowScroller from 'react-virtualized/dist/commonjs/WindowScroller';
|
||||
import AutoSizer from 'react-virtualized/dist/commonjs/AutoSizer';
|
||||
import VList from 'react-virtualized/dist/commonjs/List';
|
||||
import InfiniteLoader from 'react-virtualized/dist/commonjs/InfiniteLoader';
|
||||
|
||||
const fakeDataUrl = 'https://randomapi.com/api/dleyg4om?key=Z51U-D9OX-SXIO-SLJ9&fmt=raw&sole';
|
||||
|
||||
class VirtualizedExample extends React.Component {
|
||||
state = {
|
||||
data: [],
|
||||
loading: false,
|
||||
}
|
||||
loadedRowsMap = {}
|
||||
getData = (callback) => {
|
||||
reqwest({
|
||||
url: fakeDataUrl,
|
||||
type: 'json',
|
||||
method: 'get',
|
||||
contentType: 'application/json',
|
||||
success: (res) => {
|
||||
callback(res);
|
||||
},
|
||||
});
|
||||
}
|
||||
componentWillMount() {
|
||||
this.getData((res) => {
|
||||
this.setState({
|
||||
data: res,
|
||||
});
|
||||
});
|
||||
}
|
||||
handleInfiniteOnLoad = ({ startIndex, stopIndex }) => {
|
||||
let data = this.state.data;
|
||||
this.setState({
|
||||
loading: true,
|
||||
});
|
||||
for (let i = startIndex; i <= stopIndex; i++) {
|
||||
// 1 means loading
|
||||
this.loadedRowsMap[i] = 1;
|
||||
}
|
||||
if (data.length > 19) {
|
||||
message.warning('Virtualized List loaded all');
|
||||
this.setState({
|
||||
loading: false,
|
||||
});
|
||||
return;
|
||||
}
|
||||
this.getData((res) => {
|
||||
data = data.concat(res);
|
||||
this.setState({
|
||||
data,
|
||||
loading: false,
|
||||
});
|
||||
});
|
||||
}
|
||||
isRowLoaded = ({ index }) => {
|
||||
return !!this.loadedRowsMap[index];
|
||||
}
|
||||
renderItem = ({ index, key, style }) => {
|
||||
const { data } = this.state;
|
||||
const item = data[index];
|
||||
return (
|
||||
<List.Item key={key} style={style}>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">{item.title}</a>}
|
||||
description={item.content}
|
||||
/>
|
||||
<div style={{ padding: 24 }}>Content</div>
|
||||
</List.Item>
|
||||
);
|
||||
}
|
||||
render() {
|
||||
const { data } = this.state;
|
||||
const vlist = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered, width }) => (
|
||||
<VList
|
||||
autoHeight
|
||||
height={height}
|
||||
isScrolling={isScrolling}
|
||||
onScroll={onChildScroll}
|
||||
overscanRowCount={2}
|
||||
rowCount={data.length}
|
||||
rowHeight={117}
|
||||
rowRenderer={this.renderItem}
|
||||
onRowsRendered={onRowsRendered}
|
||||
scrollTop={scrollTop}
|
||||
width={width}
|
||||
/>
|
||||
);
|
||||
const autoSize = ({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered }) => (
|
||||
<AutoSizer disableHeight>
|
||||
{({ width }) => vlist({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered, width })}
|
||||
</AutoSizer>
|
||||
);
|
||||
const infiniteLoader = ({ height, isScrolling, onChildScroll, scrollTop }) => (
|
||||
<InfiniteLoader
|
||||
isRowLoaded={this.isRowLoaded}
|
||||
loadMoreRows={this.handleInfiniteOnLoad}
|
||||
rowCount={data.length}
|
||||
>
|
||||
{({ onRowsRendered }) => autoSize({ height, isScrolling, onChildScroll, scrollTop, onRowsRendered })}
|
||||
</InfiniteLoader>
|
||||
);
|
||||
return (
|
||||
<List>
|
||||
<WindowScroller scrollElement={null}>
|
||||
{infiniteLoader}
|
||||
</WindowScroller>
|
||||
{this.state.loading && <Spin style={{ position: 'absolute', bottom: 0, left: '50%' }} />}
|
||||
</List>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
ReactDOM.render(<VirtualizedExample />, mountNode);
|
||||
````
|
@ -16,38 +16,34 @@ List with avatar and description.
|
||||
````jsx
|
||||
import { List, Avatar } from 'antd';
|
||||
|
||||
const data = [
|
||||
{
|
||||
title: 'Ant Design Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Ant Design Title 4',
|
||||
},
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
>
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">Ant design</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
</List>
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src="https://zos.alipayobjects.com/rmsportal/ODTLcjxAfvqbxHnVXCYX.png" />}
|
||||
title={<a href="https://ant.design">{item.title}</a>}
|
||||
description="Ant Design, a design language for background applications, is refined by Ant UED Team"
|
||||
/>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -16,28 +16,30 @@ Responsive Grid List.
|
||||
````jsx
|
||||
import { List, Card } from 'antd';
|
||||
|
||||
const data = [
|
||||
{
|
||||
title: 'Title 1',
|
||||
},
|
||||
{
|
||||
title: 'Title 2',
|
||||
},
|
||||
{
|
||||
title: 'Title 3',
|
||||
},
|
||||
{
|
||||
title: 'Title 4',
|
||||
},
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<List
|
||||
grid={{ gutter: 16, xs: 2, sm: 2, md: 4, lg: 4, xl: 6 }}
|
||||
>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
<List.Item>
|
||||
<Card title="Card title">Card content</Card>
|
||||
</List.Item>
|
||||
</List>
|
||||
dataSource={data}
|
||||
renderItem={item => (
|
||||
<List.Item>
|
||||
<Card title={item.title}>Card content</Card>
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -16,15 +16,19 @@ Simple List.
|
||||
````jsx
|
||||
import { List } from 'antd';
|
||||
|
||||
const data = [
|
||||
'Racing car sprays burning fuel into crowd.',
|
||||
'Japanese princess to wed commoner.',
|
||||
'Australian walks 100km after outback crash.',
|
||||
'Man charged over missing wedding girl.',
|
||||
'Los Angeles battles huge wildfires.',
|
||||
];
|
||||
|
||||
ReactDOM.render(
|
||||
<List
|
||||
itemLayout="horizontal"
|
||||
>
|
||||
<List.Item>Racing car sprays burning fuel into crowd.</List.Item>
|
||||
<List.Item>Japanese princess to wed commoner.</List.Item>
|
||||
<List.Item>Australian walks 100km after outback crash.</List.Item>
|
||||
<List.Item>Man charged over missing wedding girl.</List.Item>
|
||||
<List.Item>Los Angeles battles huge wildfires.</List.Item>
|
||||
</List>
|
||||
dataSource={data}
|
||||
renderItem={item => (<List.Item>{item}</List.Item>)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -42,23 +42,24 @@ const IconText = ({ type, text }) => (
|
||||
);
|
||||
|
||||
ReactDOM.render(
|
||||
<List itemLayout="vertical" pagination={pagination}>
|
||||
{
|
||||
listData.map(item => (
|
||||
<List.Item
|
||||
key={item.title}
|
||||
actions={[<IconText type="star-o" text="156" />, <IconText type="like-o" text="156" />, <IconText type="message" text="2" />]}
|
||||
extra={<img width={272} alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png" />}
|
||||
>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src={item.avatar} />}
|
||||
title={<a href={item.href}>{item.title}</a>}
|
||||
description={item.description}
|
||||
/>
|
||||
{item.content}
|
||||
</List.Item>
|
||||
))
|
||||
}
|
||||
</List>
|
||||
<List
|
||||
itemLayout="vertical"
|
||||
pagination={pagination}
|
||||
dataSource={listData}
|
||||
renderItem={item => (
|
||||
<List.Item
|
||||
key={item.title}
|
||||
actions={[<IconText type="star-o" text="156" />, <IconText type="like-o" text="156" />, <IconText type="message" text="2" />]}
|
||||
extra={<img width={272} alt="logo" src="https://gw.alipayobjects.com/zos/rmsportal/mqaQswcyDLcXyDKnZfES.png" />}
|
||||
>
|
||||
<List.Item.Meta
|
||||
avatar={<Avatar src={item.avatar} />}
|
||||
title={<a href={item.href}>{item.title}</a>}
|
||||
description={item.description}
|
||||
/>
|
||||
{item.content}
|
||||
</List.Item>
|
||||
)}
|
||||
/>
|
||||
, mountNode);
|
||||
````
|
||||
|
@ -20,12 +20,9 @@ A list can be used to display content related to a single subject. The content c
|
||||
| bordered | - | string \| boolean | false |
|
||||
| loading | -| boolean | false |
|
||||
| itemLayout | - | string | - |
|
||||
| showLoadMore | -| boolean | false |
|
||||
| loadingMore | - | boolean | false |
|
||||
| onMoreClick | -| function | - |
|
||||
| loadMore | -| string\|ReactNode | - |
|
||||
| pagination | - | boolean \| object | false |
|
||||
| grid | - | object | - |
|
||||
| infinite | - | object | - |
|
||||
|
||||
### List grid props
|
||||
| Property | Description | Type | Default |
|
||||
@ -38,13 +35,6 @@ A list can be used to display content related to a single subject. The content c
|
||||
| lg | `≥1200px` - | number | - |
|
||||
| xl | `≥1600px` - | number | - |
|
||||
|
||||
### List infinite props
|
||||
| Property | Description | Type | Default |
|
||||
---------|-------------|------|---------
|
||||
| onLoad | - | function | - |
|
||||
| offset | - | number | 0 |
|
||||
| loading | - | boolean | - |
|
||||
|
||||
### List.Item
|
||||
|
||||
| Property | Description | Type | Default |
|
||||
@ -59,4 +49,3 @@ A list can be used to display content related to a single subject. The content c
|
||||
| avatar | - | ReactNode | - |
|
||||
| title | - | string\|ReactNode | - |
|
||||
| description | - | string\|ReactNode | - |
|
||||
|
||||
|
@ -1,14 +1,10 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import classNames from 'classnames';
|
||||
import addEventListener from 'rc-util/lib/Dom/addEventListener';
|
||||
|
||||
import Spin from '../spin';
|
||||
import Icon from '../icon';
|
||||
import Pagination from '../pagination';
|
||||
import Button from '../button';
|
||||
import { Row } from '../grid';
|
||||
import { throttleByAnimationFrameDecorator } from '../_util/throttleByAnimationFrame';
|
||||
|
||||
import Item from './Item';
|
||||
|
||||
@ -22,60 +18,21 @@ export interface ListGridType {
|
||||
xl?: 1 | 2 | 3 | 4 | 6 | 8 | 12 | 24;
|
||||
}
|
||||
|
||||
export interface InfinitePropType {
|
||||
onLoad?: any;
|
||||
loading?: boolean;
|
||||
offset?: number;
|
||||
}
|
||||
|
||||
export interface ListProps {
|
||||
bordered?: boolean;
|
||||
className?: string;
|
||||
children?: React.ReactNode;
|
||||
extra?: React.ReactNode;
|
||||
id?: string;
|
||||
itemLayout: string;
|
||||
loading?: boolean;
|
||||
showLoadMore?: boolean;
|
||||
loadingMore?: boolean;
|
||||
onLoadMore?: React.FormEventHandler<any>;
|
||||
loadMore?: React.ReactNode;
|
||||
pagination?: any;
|
||||
prefixCls?: string;
|
||||
grid?: ListGridType;
|
||||
infinite?: InfinitePropType;
|
||||
}
|
||||
|
||||
function getDefaultTarget() {
|
||||
return typeof window !== 'undefined' ?
|
||||
window : null;
|
||||
}
|
||||
|
||||
function getOffsetTop(element?: HTMLElement): number {
|
||||
if (!element) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!element.getClientRects().length) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const rect = element.getBoundingClientRect();
|
||||
|
||||
if (rect.width || rect.height) {
|
||||
const doc = element.ownerDocument;
|
||||
const docElem = doc.documentElement;
|
||||
return rect.top - docElem.clientTop;
|
||||
}
|
||||
|
||||
return rect.top;
|
||||
}
|
||||
|
||||
function getViewportHeight() {
|
||||
const win = getDefaultTarget();
|
||||
if (!win) {
|
||||
return 0;
|
||||
}
|
||||
return Math.max(win.document.documentElement.clientHeight, win.innerHeight || 0);
|
||||
itemLayout?: string;
|
||||
rowKey?: any;
|
||||
dataSource: any;
|
||||
renderItem: any;
|
||||
}
|
||||
|
||||
export default class List extends Component<ListProps> {
|
||||
@ -85,23 +42,7 @@ export default class List extends Component<ListProps> {
|
||||
grid: PropTypes.any,
|
||||
};
|
||||
|
||||
scrollEvent: any;
|
||||
resizeEvent: any;
|
||||
timeout: any;
|
||||
|
||||
events = [
|
||||
'resize',
|
||||
'scroll',
|
||||
'touchstart',
|
||||
'touchmove',
|
||||
'touchend',
|
||||
'pageshow',
|
||||
'load',
|
||||
];
|
||||
infiniteLoaded = false;
|
||||
eventHandlers = {};
|
||||
|
||||
private node: any;
|
||||
private keys = {};
|
||||
|
||||
getChildContext() {
|
||||
return {
|
||||
@ -109,76 +50,25 @@ export default class List extends Component<ListProps> {
|
||||
};
|
||||
}
|
||||
|
||||
componentDidMount() {
|
||||
if (!this.isInfinite()) {
|
||||
return;
|
||||
}
|
||||
const target = getDefaultTarget;
|
||||
renderItem = (item, index) => {
|
||||
const { dataSource, renderItem, rowKey } = this.props;
|
||||
let key;
|
||||
|
||||
// Wait for parent component ref has its value
|
||||
this.timeout = setTimeout(() => {
|
||||
this.setTargetEventListeners(target);
|
||||
});
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
if (!this.isInfinite()) {
|
||||
return;
|
||||
}
|
||||
this.clearEventListeners();
|
||||
clearTimeout(this.timeout);
|
||||
(this.infiniteLoad as any).cancel();
|
||||
}
|
||||
|
||||
getNode = (n) => {
|
||||
this.node = n;
|
||||
}
|
||||
|
||||
isInfinite() {
|
||||
const { infinite } = this.props;
|
||||
return infinite && (typeof infinite.onLoad === 'function');
|
||||
}
|
||||
|
||||
setTargetEventListeners(getTarget) {
|
||||
const target = getTarget();
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
this.clearEventListeners();
|
||||
|
||||
this.events.forEach(eventName => {
|
||||
this.eventHandlers[eventName] = addEventListener(target, eventName, this.infiniteLoad);
|
||||
});
|
||||
}
|
||||
|
||||
clearEventListeners() {
|
||||
this.events.forEach(eventName => {
|
||||
const handler = this.eventHandlers[eventName];
|
||||
if (handler && handler.remove) {
|
||||
handler.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@throttleByAnimationFrameDecorator()
|
||||
infiniteLoad() {
|
||||
const { infinite = {} } = this.props;
|
||||
const targetElement = this.node;
|
||||
|
||||
if (this.infiniteLoaded || !targetElement) {
|
||||
return;
|
||||
if (typeof rowKey === 'function') {
|
||||
key = rowKey(dataSource[index]);
|
||||
} else if (typeof rowKey === 'string') {
|
||||
key = dataSource[rowKey];
|
||||
} else {
|
||||
key = dataSource.key;
|
||||
}
|
||||
|
||||
const viewportHeight = getViewportHeight();
|
||||
const eleOffsetTop = getOffsetTop(targetElement);
|
||||
const bottomPositionY = eleOffsetTop + targetElement.offsetHeight - viewportHeight + (infinite.offset || 0);
|
||||
|
||||
if (bottomPositionY < 0) {
|
||||
this.infiniteLoaded = true;
|
||||
infinite.onLoad(() => {
|
||||
this.infiniteLoaded = false;
|
||||
});
|
||||
if (!key) {
|
||||
key = `list-item-${index}`;
|
||||
}
|
||||
|
||||
this.keys[index] = key;
|
||||
|
||||
return renderItem(item, index);
|
||||
}
|
||||
|
||||
render() {
|
||||
@ -188,14 +78,13 @@ export default class List extends Component<ListProps> {
|
||||
children,
|
||||
loading = false,
|
||||
itemLayout,
|
||||
showLoadMore = false,
|
||||
loadingMore = false,
|
||||
onLoadMore = (() => {
|
||||
}),
|
||||
loadMore,
|
||||
pagination = false,
|
||||
prefixCls = 'ant-list',
|
||||
grid,
|
||||
infinite = {},
|
||||
dataSource = [],
|
||||
rowKey,
|
||||
renderItem,
|
||||
...rest,
|
||||
} = this.props;
|
||||
|
||||
@ -204,50 +93,42 @@ export default class List extends Component<ListProps> {
|
||||
[`${prefixCls}-bordered`]: bordered,
|
||||
[`${prefixCls}-loading`]: loading,
|
||||
[`${prefixCls}-grid`]: grid,
|
||||
[`${prefixCls}-infinite`]: infinite.onLoad,
|
||||
});
|
||||
|
||||
const moreButton = (
|
||||
<Button onClick={onLoadMore}>
|
||||
<Icon type="loading"/>
|
||||
加载中...
|
||||
</Button>
|
||||
);
|
||||
|
||||
const moreContent = (
|
||||
<div className={`${prefixCls}-more`}>
|
||||
{loadingMore ? moreButton : <Button onClick={onLoadMore}>加载更多...</Button>}
|
||||
</div>
|
||||
);
|
||||
|
||||
const paginationContent = (
|
||||
<div className={`${prefixCls}-pagination`}>
|
||||
<Pagination {...pagination} />
|
||||
</div>
|
||||
);
|
||||
|
||||
const childrenList = React.Children.map(dataSource.map((item: any, index) => this.renderItem(item, index)),
|
||||
(child: any, index) => React.cloneElement(child, {
|
||||
key: this.keys[index],
|
||||
}),
|
||||
);
|
||||
|
||||
const childrenContent = grid ? (
|
||||
<Row gutter={grid.gutter}>{children}</Row>
|
||||
) : children;
|
||||
<Row gutter={grid.gutter}>{childrenList}</Row>
|
||||
) : childrenList;
|
||||
|
||||
const content = loading ? (
|
||||
<Spin>
|
||||
{childrenContent}
|
||||
{showLoadMore && moreContent}
|
||||
{(!showLoadMore && pagination) && paginationContent}
|
||||
{loadMore}
|
||||
{(!loadMore && pagination) && paginationContent}
|
||||
</Spin>
|
||||
) : (
|
||||
) : (
|
||||
<div>
|
||||
{childrenContent}
|
||||
{showLoadMore && moreContent}
|
||||
{(!showLoadMore && pagination) && paginationContent}
|
||||
{infinite.loading && (<div className={`${prefixCls}-spin`}><Spin /></div>)}
|
||||
{loadMore}
|
||||
{(!loadMore && pagination) && paginationContent}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={classString} {...rest} ref={this.getNode}>
|
||||
<div className={classString} {...rest}>
|
||||
{content}
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -21,12 +21,9 @@ cols: 1
|
||||
| bordered | 是否展示边框 | boolean | false |
|
||||
| loading | 当卡片内容还在加载中时,可以用 loading 展示一个占位 | boolean | false |
|
||||
| itemLayout | 设置 List.Item 布局, 设置成 vertical 则竖直样式显示, 默认横排 | string | - |
|
||||
| showLoadMore | 是否显示加载更多按钮 | boolean | false |
|
||||
| loadingMore | 是否显示加载更多按钮的 loading 状态 | boolean | false |
|
||||
| onMoreClick | 点击 more 按钮的回调 | function | - |
|
||||
| loadMore | 加载更多 | string\|ReactNode | - |
|
||||
| pagination | 对应的 pagination 配置, 设置 false 不显示 | boolean \| object | false |
|
||||
| grid | 列表栅格 | object | - |
|
||||
| infinite | 无限加载配置 | object | - |
|
||||
|
||||
### List grid props
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
@ -39,13 +36,6 @@ cols: 1
|
||||
| lg | `≥1200px` 展示的列数 | number | - |
|
||||
| xl | `≥1600px` 展示的列数 | number | - |
|
||||
|
||||
### List infinite props
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
---------|-------------|------|---------
|
||||
| onLoad | 无限加载的回调函数 | function | - |
|
||||
| offset | 触发加载位置的偏移量 | number | 0 |
|
||||
| loading | 显示无限加载时的 loading | boolean | - |
|
||||
|
||||
### List.Item
|
||||
|
||||
| 参数 | 说明 | 类型 | 默认值 |
|
||||
|
@ -5,7 +5,10 @@
|
||||
|
||||
.@{list-prefix-cls} {
|
||||
.reset-component;
|
||||
|
||||
position: relative;
|
||||
* {
|
||||
outline: none;
|
||||
}
|
||||
&-more, &-pagination {
|
||||
margin-top: 24px;
|
||||
text-align: center;
|
||||
@ -162,6 +165,13 @@
|
||||
}
|
||||
}
|
||||
|
||||
.@{list-prefix-cls}-empty {
|
||||
color: @text-color-secondary;
|
||||
padding: 16px 0;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@media screen and (max-width: @screen-md) {
|
||||
.@{list-prefix-cls} {
|
||||
&-item {
|
||||
@ -170,6 +180,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{list-prefix-cls}-vertical {
|
||||
.@{list-prefix-cls}-item {
|
||||
&-extra {
|
||||
@ -188,6 +199,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.@{list-prefix-cls}-vertical {
|
||||
.@{list-prefix-cls}-item {
|
||||
&-extra-wrap {
|
||||
|
@ -3,7 +3,5 @@ import './index.less';
|
||||
|
||||
// style dependencies
|
||||
import '../../spin/style';
|
||||
import '../../icon/style';
|
||||
import '../../pagination/style';
|
||||
import '../../button/style';
|
||||
import '../../grid/style';
|
||||
|
@ -135,9 +135,11 @@
|
||||
"react-document-title": "^2.0.1",
|
||||
"react-dom": "^15.0.0",
|
||||
"react-github-button": "^0.1.1",
|
||||
"react-infinite-scroller": "^1.0.15",
|
||||
"react-intl": "^2.0.1",
|
||||
"react-sublime-video": "^0.2.0",
|
||||
"react-test-renderer": "^15.5.4",
|
||||
"react-virtualized": "^9.10.1",
|
||||
"reqwest": "^2.0.5",
|
||||
"rimraf": "^2.5.4",
|
||||
"stylelint": "^8.0.0",
|
||||
|
Loading…
Reference in New Issue
Block a user