基于react的瀑布流组件

在日常工作的过程中,搭建瀑布流式的页面布局是一个经常出现的业务场景。

背景

瀑布流布局的定义

一般来说,把多列等宽、元素高度不一的页面布局认为是瀑布流布局.

基于react的瀑布流组件_第1张图片

瀑布流的特点

瀑布流的特点通常包括以下:

  • 多列布局
  • 每列等宽
  • 高度参差不齐(这是和常规列表不一样的地方,造成不规则的效果)
  • 大量元素展示(通常是图片或图文并存)

因此,当我们根据获得的列表进行展示的时候,引申出排版的规律:

  • 优先插入高度小的那一列
  • 同等高度,优先左侧

动手开工

组件属性

根据上面的归纳,可以为Waterfall组件得到以下属性

  • list: 传入需要进行瀑布流布局的数据列表,每个元素必须包含height和width字段
  • cols: 瀑布流布局展示的列数
  • width: 瀑布流布局的总宽度,单位为px
  • margin: 列与列之间的间隔距离,默认为20,单位为px
 

计算每列的宽度

根据colswidthmargin,计算出每列的宽度。

const defaultColWidth = (width - (cols - 1) * margin) / cols 

分配&插入队列

接下来,要实现一个插入分配的函数。

1.依据cols的数目,创建一个用于存储元素的二维数组arr
2.创建一个用于记录每列高度的数组
3.遍历传入的list1.获取元素的heightwidth字段2.根据之前得到的每列宽度,计算出元素实际的显示高度3.获取所有列的当前高度,把元素插入到高度最小列,并更新该列的宽度
4.返回所有元素都插入完成arr

显示瀑布流

根据上一步得到的数组进行显示,大功告成。

基于react的瀑布流组件_第2张图片

代码展示

特别说明一下,这里有一个字段fields,是作为业务展示数据传入,这里可以针对业务场景,做定制化的展示,这里就不再赘述。

function allocateItems( ls,len,colWidth ){/** 各个瀑布流的内容列表 */const arr = []/** 各个瀑布流的高度列表 */const heightArr = []// 初始化瀑布流的内容列表和高度列表for (let i = 0; i < len; i++) {arr.push([])heightArr.push(0)}/** 获取高度最小的流的索引值 */function getIndexOfMinHeightFlow() {let minH = Number.MAX_SAFE_INTEGERlet minIndex = 0heightArr.forEach((h, index) => {if (h < minH) {minH = hminIndex = index}})return minIndex}// 通过计算展示高度,设置瀑布流的内容列表ls.forEach((item, idx) => {const index = getIndexOfMinHeightFlow()item.displayHeight = (item.height * colWidth) / item.widtharr[index].push(item)heightArr[index] += item.displayHeight})return arr
}

const Waterfall = (props) => {const { list, cols = 1, width, margin = 20, fields } = propsconst defaultColWidth = (width - (cols - 1) * margin) / colsconst [colList, setColList] = useState(allocateItems(list, cols, defaultColWidth))useEffect(() => {setColList(allocateItems(list, cols, defaultColWidth))}, [list, cols, defaultColWidth])return (
{colList.map((col, fIndex) => (
    {col.map((item, iIndex) => ({ /* 业务展示UI */ }))}
))}
) }

最后补充

上面的代码逻辑假定了已知元素的高宽,但是如果后端接口没有给我们图片大小的话,我们要怎样做呢?

可以是在allocateItems()里面,添加new Image请求图片并监听onLoad事件,获取图片的实际大小再进行计算。

最后

整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。

有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享

部分文档展示:



文章篇幅有限,后面的内容就不一一展示了

有需要的小伙伴,可以点下方卡片免费领取

你可能感兴趣的:(react.js,javascript,前端)