在日常工作的过程中,搭建瀑布流式的页面布局是一个经常出现的业务场景。
一般来说,把多列等宽、元素高度不一的页面布局认为是瀑布流布局.
瀑布流的特点通常包括以下:
因此,当我们根据获得的列表进行展示的时候,引申出排版的规律:
根据上面的归纳,可以为Waterfall
组件得到以下属性
list
: 传入需要进行瀑布流布局的数据列表,每个元素必须包含height和width字段cols
: 瀑布流布局展示的列数width
: 瀑布流布局的总宽度,单位为pxmargin
: 列与列之间的间隔距离,默认为20,单位为px<Waterfall list={waterfallList} cols={4} width={450} margin={10}></Waterfall>
根据cols
、 width
和margin
,计算出每列的宽度。
const defaultColWidth = (width - (cols - 1) * margin) / cols
接下来,要实现一个插入分配的函数。
1.依据cols
的数目,创建一个用于存储元素的二维数组arr
2.创建一个用于记录每列高度的数组
3.遍历传入的list
1.获取元素的height
和width
字段2.根据之前得到的每列宽度,计算出元素实际的显示高度3.获取所有列的当前高度,把元素插入到高度最小列,并更新该列的宽度
4.返回所有元素都插入完成arr
根据上一步得到的数组进行显示,大功告成。
特别说明一下,这里有一个字段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 (<div className='waterfall' style={{ width: width + 'px' }}>{colList.map((col, fIndex) => (<ul className='waterfall-list' style={{ width: defaultColWidth + 'px' }} key={'flow_' + fIndex}>{col.map((item, iIndex) => (<liclassName='waterfall-item'key={'flow_' + fIndex + '_item_' + iIndex + '_' + item.displayHeight}style={{ height: item.displayHeight + 'px' }}title={ || '' }>{ /* 业务展示UI */ }</li>))}</ul>))}</div>)
}
上面的代码逻辑假定了已知元素的高宽,但是如果后端接口没有给我们图片大小的话,我们要怎样做呢?
可以是在allocateItems()
里面,添加new Image
请求图片并监听onLoad
事件,获取图片的实际大小再进行计算。
整理了一套《前端大厂面试宝典》,包含了HTML、CSS、JavaScript、HTTP、TCP协议、浏览器、VUE、React、数据结构和算法,一共201道面试题,并对每个问题作出了回答和解析。
有需要的小伙伴,可以点击文末卡片领取这份文档,无偿分享
部分文档展示:
文章篇幅有限,后面的内容就不一一展示了
有需要的小伙伴,可以点下方卡片免费领取
本文发布于:2024-01-28 15:40:02,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/17064276068464.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |