小程序瀑布流实现
创始人
2024-03-03 23:53:37

什么是瀑布流布局

瀑布流布局,一般等宽,不等高的列表排列

原理是找出高度之和最小的那一列,在高度最小列继续添加元素

可以通过 absolute 定位实现,动态计算每一项的 topleft

在这里插入图片描述

封装瀑布流方法

function getAllRect(context, selector) {return new Promise(function (resolve) {wx.createSelectorQuery().in(context).selectAll(selector).boundingClientRect().exec(function (rect) {if (rect === void 0) {rect = []}return resolve(rect[0])})})
}/*** 瀑布流* @param {*} context 页面或组件this对象* @param {string} selector 选择器* @param {Object} options* @param {number=375} options.width 屏幕宽度* @param {number=2} options.column 列数* @param {number|string} options.gap 每列直接的间隙* @param {number=0} options.padding 整个列表左右的padding* @param {number=0}* @returns {Array} 计算每项的top、left、height的数组*/
async function waterFall(context, selector, options = {}) {let items = await getAllRect(context, selector)if (items.length <= 0) return []let { gap = 15, column = 2, padding = 0, width = 375, firstColumnToTop = 0 } = options// 1- 确定列数  = 页面的宽度 / 图片的宽度,单例的宽度let itemWidth = items[0].width// 定义每一列之间的间隙 pxif (gap === 'auto') {gap = (width - itemWidth * column) / (column - 1)}let _columnHeightArr = [] // 保存每列高度let result = []for (let i = 0, len = items.length; i < len; i++) {if (i < column) {// 2- 确定第一行let top = firstColumnToToplet left = (itemWidth + gap) * i + padding// 瀑布流列表左右paddingif (i === 0 || i === len - 1) {left = padding}_columnHeightArr.push(items[i].height - top)result.push({top,left,height: items[i].height,})} else {// 其他行// 3- 找到数组中最小高度  和 它的索引let minHeight = Math.min(..._columnHeightArr)let minIndex = _columnHeightArr.findIndex((item) => item === minHeight)// 4- 设置下一行的第一个盒子位置// top值就是最小列的高度 + gapresult.push({top: _columnHeightArr[minIndex] + gap,left: result[minIndex].left,height: items[i].height,})// 5- 修改最小列的高度// 最小列的高度 = 当前自己的高度 + 拼接过来的高度 + 间隙的高度_columnHeightArr[minIndex] = _columnHeightArr[minIndex] + items[i].height}}return result
}

使用

vim demo.wxml

    {height}}">{list}}" wx:key="index">{ item.top }}px;left:{{ item.left }}px"bindtap="handleItem" data-item="{{item}}">{ {imgUrl:item.goodsIcon} }}" isAllowCash="{{true}}">{{item.goodsName}}{{item.price}}

vim demo.js

// 需要在节点加载到页面后调用
onReady() {const { screenWidth, list } = this.datawaterFall(this, '.goods_item', { width: screenWidth, gap: 'auto' }).then((arr) => {if (!arr.length) returnlet lastNode = arr[arr.length - 1]let height = lastNode.top + lastNode.height + 'px'this.setData({list: list.map((item, index) => ({ ...item, ...arr[index] })),height,})})
}

效果

在这里插入图片描述

小结

既然都封装成函数了,为什么不封装成组件调用呢?

组件调用可以参考这个小程序的瀑布流组件me-waterfall

我看了这个组件的源码,用到组件间关系来实现瀑布流结构,整个瀑布流组件内部也需要父子组件关系,父组件监听子组件插入元素,获取元素的动态高度,往高度最小列添加新元素。

但是我引入使用,在组件内使用me-waterfall 组件,组件间关系方法 linked 不生效,官方论坛也找不到原因,便弃用。
类似这样的结构:




{list}}" wx:key="index">{item.imgUrl}}" style="width:100%;height:{{item.height}}px" />

于是,自己封装一个方法使用。便有了此文。

封装成方法也有优点,不需要引入组件,简单引入一下方法调用即可。

相关内容

热门资讯

demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...