需要
在业务中须要在web页面依据搜寻的后果渲染出瀑布流款式的后果页面,我实现成果如下(感觉不太称心,他并不是通过计算最小高度而后主动填补,而是依照几列几行来一个个填补,前面有更深刻的研究会更新,这是一种赶工实现的形式):
实现办法
尝试了间接应用flex布局,存在较大的缺点,尽管看似实现了,但对于特地的图片显示还是很奇怪,不够贴合,起初查问了几种插件,不是说他们都不好,试下的成果应该是相似的,都是通过计算图形的宽高来进行布局的,不过有些对于数据中蕴含的信息要求比拟高,让后盾在我的数据外面塞图形宽高曾经是我这个小前端的极限了!!最初找到了一个 react-grid-layout 插件,感激大佬小翼在答复中提供的几种插件。
代码
import React, { Component } from "react";import styles from "./styles.module.less";// 引入lodashimport _ from "lodash";// 引入组件import RGL, { WidthProvider } from "react-grid-layout";// 包装组件const ReactGridLayout = WidthProvider(RGL);// 定义案例数组数据const items = [ { url: "https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=384124318,1246746555&fm=26&gp=0.jpg", width: 540, height: 300, }, { url: "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2435568812,3959731342&fm=11&gp=0.jpg", width: 499, height: 320, }, { url: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3341500380,460051199&fm=11&gp=0.jpg", width: 604, height: 300, }, { url: "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=2435568812,3959731342&fm=11&gp=0.jpg", width: 499, height: 320, }, { url: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3341500380,460051199&fm=11&gp=0.jpg", width: 604, height: 300, }, { url: "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3426709235,3578542279&fm=26&gp=0.jpg", width: 500, height: 210, }, { url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1322120441,3602413475&fm=26&gp=0.jpg", width: 400, height: 183, }, { url: "https://ss2.bdstatic.com/70cFvnSh_Q1YnxGkpoWK1HF6hhy/it/u=3426709235,3578542279&fm=26&gp=0.jpg", width: 500, height: 210, }, { url: "https://ss1.bdstatic.com/70cFuXSh_Q1YnxGkpoWK1HF6hhy/it/u=3341500380,460051199&fm=11&gp=0.jpg", width: 604, height: 300, }, { url: "https://ss0.bdstatic.com/70cFvHSh_Q1YnxGkpoWK1HF6hhy/it/u=1322120441,3602413475&fm=26&gp=0.jpg", width: 400, height: 183, }, { url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fi2.hdslb.com%2Fbfs%2Farchive%2F3c7a5b24b38ac3216182e0bf026622801d10c3fa.jpg&refer=http%3A%2F%2Fi2.hdslb.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1612319581&t=9486804e3256336fd0d2c2865d929d6c", width: 1728, height: 1080, }, { url: "https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic.51yuansu.com%2Fpic3%2Fcover%2F02%2F85%2F29%2F5a61c19d6a659_610.jpg&refer=http%3A%2F%2Fpic.51yuansu.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=jpeg?sec=1612319668&t=aaa48c2a20b18f021f8058d7bd882dfb", width: 610, height: 1295, },];// 定义一个父组件,次要是为了进行容器大小的变动监听,而后动静设置高度export default class About extends Component { constructor(props) { super(props); // 行高初始化,这是我本人的行高,依据以后容器大小计算出来的 this.state = { rowHeight: 110 }; } componentDidMount() { // 初始化size监听函数 this.screenChange(); } // 卸载size监听函数 componentWillUnmount() { window.removeEventListener("resize", this.resize); } // size监听函数 screenChange = () => { window.addEventListener("resize", this.resize); }; // 区域宽高变动时触发行高的变动 resize = () => { const box = document.getElementById("watar-fall"); let width = box.clientWidth; let rowHeight = (width - 100) / 12; this.setState({ rowHeight }); console.log(width); }; render() { // 将行高作为props传入子组件 const { rowHeight } = this.state; return ( <div className={styles.bside_main_container} id="watar-fall"> <WaterFall rowHeight={rowHeight} items={items}></WaterFall> </div> ); }}// 定义的瀑布流子组件,真是利用能够独自封装在内部class WaterFall extends Component { // 默认的props static defaultProps = { className: "layout", isDraggable: false, isResizable: false, cols: 12, rowHeight: 110, }; constructor(props) { super(props); // 初始化定义layout 和渲染的数据 this.state = { layout: this.generateLayout([]), data: [] }; } // 加载的时候更新layout和data componentDidMount() { this.setState({ data: [...this.props.items], layout: this.generateLayout(this.props.items), }); } // 生成每一个瀑布流内item 的函数 generateDOM = () => { const { data } = this.state; return _.map(_.range(data.length), function (i) { return ( // 这里的key值和layout外面的要对应,所以不要用其余值代替 <div key={i} className={styles.box}> {/*在这里能够自定义你要的显示款式 */} <img src={data[i].url} alt="ff" style={{ width: "100%" }}></img> </div> ); }); }; // 生成layout的数组函数 generateLayout = (items) => { // 循环数据返回相应的layout return _.map(new Array(items.length), function (item, i) { // 在这里设置每一个图片的高度。我是通过图片的宽而后依据所占行的比例,计算出来的等比高度 let y = (3 / items[i].width) * items[i].height; return { x: (i * 3) % 12, // 每个图片的起始x点 ,因为是4列,所以在12列外面是3列一个图片 y: Math.floor(i / 4) * y, // 距离四个换行 w: 3, // 图片占的列数 h: y, // 计算所得的图片高度 i: i.toString(), // layout的key值 }; }); }; render() { return ( <div className={styles.container}> {/* 传入参数并生成瀑布流 */} <ReactGridLayout layout={this.state.layout} {...this.props}> {this.generateDOM()} </ReactGridLayout> </div> ); }}
总结
这次根本的实现是这样,这个组件原本更弱小的中央应该是在可拖拽的方面,我这算是千里之堤;溃于蚁穴了,前面如果有工夫再钻研一下其余瀑布流或者本人写一个js组件吧。(如果我写的有什么问题,欢送斧正!)