react-组件分享MasonryLayout瀑布流布局react-masonry-css

react-masonry-css


瀑布流布局

在视觉上表现为参差不齐的多栏布局,随着页面滚动条向下滚动,新数据不断被加载进来。


实现步骤

  1. 首先实现单独的内容展现
  2. 再次实现一组内容的瀑布流展现,比如20条
  3. 最后滚动不断加入新的内容

代码

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


你可能感兴趣的:(#,react,react.js,css,javascript)