react-masonry-css
瀑布流布局
在视觉上表现为参差不齐的多栏布局,随着页面滚动条向下滚动,新数据不断被加载进来。
实现步骤
- 首先实现单独的内容展现
- 再次实现一组内容的瀑布流展现,比如20条
- 最后滚动不断加入新的内容
代码
react-masonry-css: 是一个以css响应实现的瀑布流布局
dummyjs: 随机模拟文本或图片
react-infinite-scroller: 滚动监听加载数据
import React, { Component } from 'react'
import _class from 'classnames'
import Dummy from 'dummyjs'
import InfiniteScroll from 'react-infinite-scroller'
import Masonry from 'react-masonry-css'
import { Button, Dropdown, Menu, Row, Card, Icon, Input } from 'antd'
const pageSize = 20
const mockData = (start) => {
let datas = []
let end = start + pageSize
for (var i = start; i < end; i++) {
let data = {}
data.id = 'mock-' + i
data.title = 'Card#' + i
data.image = Dummy.src(500, 400)
data.content = Dummy.text(20, 60)
data.collapsed = true
datas.push(data)
}
return datas
}
/**
*
* 瀑布流布局
* @class MasonryLayoutExample
* @extends {React.Component}
*/
class MasonryLayoutExample extends React.Component {
state = {
breakpointColumnsObj: {
default: 5,
1400: 4,
1100: 3,
700: 2,
500: 1
},
hasMore: true,
datas: []
}
UNSAFE_componentWillMount() {
};
componentWillUnmount() {
this.setState = () => {
return
}
}
componentDidMount() {
this.loadMoreData()
}
/**
*
* 加载数据
* @memberof MasonryLayoutExample
*/
loadMoreData = (page = 1) => {
const { datas } = this.state
if (datas.length >= 200) {
console.log('加载完成')
return false
}
let start = (page - 1) * pageSize + 1
let newData = mockData(start)
this.setState({ datas: [...datas, ...newData] })
}
/**
*
* 拦截数据变化
* @param {*} datas
* @memberof MasonryLayoutExample
*/
handlerDataChange = (datas) => {
console.log('操作datas==>', datas)
this.setState({ datas })
}
renderContainer = (datas) => {
return datas.map((item, key) => {
/** body区域样式 */
let defineBodyStyle = item.collapsed ? { padding: '15px' } : { padding: '0px' }
/** 箭头旋转 */
let caretRotate = item.collapsed ? 0 : 180
return (
<Card key={item.id} title={item.title} bordered={false}
hoverable
bodyStyle={defineBodyStyle}
actions={[
<Icon type='caret-up' key='caret-up' rotate={caretRotate}
onClick={() => {
item.collapsed = !item.collapsed
this.handlerDataChange(datas)
}}
/>,
<Icon type='delete' key='delete' />,
<Icon type='edit' key='ellipsis' />,
]}
>
{
item.collapsed ? <React.Fragment>
<div><img src={item.image} style={{ width: '100%' }} /></div>
<div>{item.content}</div>
</React.Fragment> : null
}
</Card>
)
})
}
render() {
return (
<React.Fragment>
{/* 下拉加载 */}
<InfiniteScroll
initialLoad={false} // 不让它进入直接加载
pageStart={1} // 设置初始化请求的页数
loadMore={this.loadMoreData}
hasMore={this.state.hasMore}
useWindow // 监听 window 滚动条
>
{/* 瀑布流 */}
<Masonry
breakpointCols={this.state.breakpointColumnsObj}
className='note-masonry-grid'
columnClassName='note-masonry-grid_column'
>
{this.renderContainer(this.state.datas)}
</Masonry>
</InfiniteScroll>
</React.Fragment >
)
}
}
export default MasonryLayoutExample