专注连锁门店会员营销管理系统
线上+线下+进销存+收银+会员2020-09-27 作者:秩名
瀑布流布局是目前很普遍的布局形式,那么小程序瀑布流要如何实现解决,网上能搜到的小程序瀑布流解决方案,要么代码复杂、逻辑混乱,要么实现不了业务功能,所以把我在项目中的实现方案给大家分享下。
最简单的实现方案,不适用有分页的场景。
这个方案简单的原因是因为仅仅使用了css的属性。
使用column-count 属性可以指定页面显示的列数,一般瀑布流都是2列,所以可以定义class
.list-masonry { column-count: 2; //2列 column-gap: 20rpx; //列间距 }
界面定义也很简单
<view class='list-masonry'> <block wx:for="{{goodsList}}" wx:key="{{item.id}}"> <template is='goodsCard' data="{{data:item}}" /> </block> </view>
其中,goodsList为页面展示的数据,goodsCard为瀑布流的卡片,这个很容易理解。
注意,瀑布流的卡片需要css属性 display: inline-block; 将卡片设置为 内联元素。image 组件设置缩放模式 mode="widthFix" 来保持图片宽高比。
column-count 属性默认是以列的形式来填充数据的。比如我们有20条数据,1 ~ 10 条数据会展示在左边第一列,11 ~ 20 条数据会展示在第二列。
如果有分页,再往数组中增加20条数据后,就会变成 1 ~ 20 条数据会在左边,21 ~ 40 条数据会展示在右边。用户体验非常差。
由于 column-fill: balance; 填充属性无效,无法指定填充顺序为行的形式。
所以这种实现方案只能一下加载完所有数据,不适用于分页。
Component实现瀑布流,功能强大,滑动流畅
通过自定义组件,用自己的思路实现瀑布流。然后在需要瀑布流的地方直接调用,方便复用。
没有Demo!! 跟着我的步骤一步一步来,就能轻松实现。
建议在项目根目录创建文件夹component,然后在该目录下创建文件夹WaterFallView,最后在WaterFallView下创建component。(鼠标右键->新建->Component)。
2. 设计瀑布流的wxml。
瀑布流的结构简单,只有左右2列。所以在设计UI的时候,布局很简单。
<view class='fall-container'> <!-- 左边一列 --> <view class='fall-left'> <block wx:for="{{leftList}}" wx:key="{{item.id}}"> <!--瀑布流内容卡片--> <template is='goodsCard' data="{{data:item}}" /> </block> </view> <!--右边一列 --> <view class='fall-right'> <block wx:for="{{rightList}}" wx:key="{{item.id}}"> <!--瀑布流内容卡片--> <template is='goodsCard' data="{{data:item}}" /> </block> </view> </view>
左右两边,一边一个View。通过这两个View 来展示瀑布流的两列。每个View对应一个数据源,由此可见,这套思路的重点是这个两个数据源的处理。每个View中的template 为瀑布流中的卡片,就不介绍了。
超过两列的瀑布流比较少见,本篇不考虑,但可用本篇的思路来实现。
.fall-container { width: 100%; display: flex; } .fall-left { display: flex; flex-direction: column; } .fall-right { display: flex; flex-direction: column; margin-left: 20rpx; }
根据上面的 wxml 结构,这个组件的核心逻辑就是如何把要展示的数据item 放入leftList、rightList这两个数组中。
如何分配数据item?这个简单,我们可以定义2个变量 leftHight、rightHight,来分别记录leftList、rightList数组中图片的高度(可以理解为左边View、右边View的高度,其实只是图片的高度,但已满足瀑布流的的需求)。当leftHight 大于 rightHight时,把数据放入rightList,并让rightHight叠加数据中图片的高度。当rightHight大于 leftHight 时,把数据放入leftList,并让leftHight 叠加数据中图片的高度。
if (leftHight == rightHight) { //第1个item放左边 leftList.push(tmp); leftHight = leftHight + tmp.itemHeight; } else if (leftHight < rightHight) { leftList.push(tmp); leftHight = leftHight + tmp.itemHeight; } else { rightList.push(tmp); rightHight = rightHight + tmp.itemHeight; }
瀑布流展示图片的时候,需要知道图片的宽高,然后根据图片的宽高比来设置 image组件的宽高。所以如果你们的数据没有宽高或宽高比,很难实现瀑布流。虽然可以通过代码获得图片宽高,但会对性能以及用户体验有很大影响,不推荐这么做。可以和后台同学商量下,看如何加上宽高数据。
Component有自己生命周期方法,甚至可以象Page一样,当做一个单独的页面使用。可以在他的生命周期方法中获得到瀑布流的宽度,以及图片的最大高度。
attached: function () { //第一个生命周期方法 wx.getSystemInfo({ success: (res) => { let percentage = 750 / res.windowWidth; //750rpx/屏幕宽度 let margin = 20 / percentage; //计算瀑布流间距 itemWidth = (res.windowWidth - margin) / 2; //计算 瀑布流展示的宽度 maxHeight = itemWidth / 0.8 //计算瀑布流的最大高度,防止长图霸屏 } }); },
拿到瀑布流的宽度后,就可以根据图片的宽高比,计算出 image 组件的宽高。
let tmp = listData[i]; //单条数据 tmp.width = parseInt(tmp.width); //图片宽度 tmp.height = parseInt(tmp.height); //图片高度 tmp.itemWidth = itemWidth //image 宽度 let per = tmp.width / tmp.itemWidth; //图片宽高比 tmp.itemHeight = tmp.height / per; //image 高度 if (tmp.itemHeight > maxHeight) { tmp.itemHeight = maxHeight; //image 高度,不超过最大高度 }
在template中,image的宽高需要声明下。单位是px,不是rpx
<image class='card-img' mode='aspectFill' style='width:{{data.itemWidth}}px;height:{{data.itemHeight}}px;' src='{{data.img}}' lazy-load> </image>
/** * 瀑布流组件 */ var leftList = new Array();//左侧集合 var rightList = new Array();//右侧集合 var leftHight = 0, rightHight = 0, itemWidth = 0, maxHeight = 0; Component({ properties: {}, data: { leftList: [],//左侧集合 rightList: [],//右侧集合 }, attached: function () { wx.getSystemInfo({ success: (res) => { let percentage = 750 / res.windowWidth; let margin = 20 / percentage; itemWidth = (res.windowWidth - margin) / 2; maxHeight = itemWidth / 0.8 } }); }, methods: { /** * 填充数据 */ fillData: function (isPull, listData) { if (isPull) { //是否下拉刷新,是的话清除之前的数据 leftList.length = 0; rightList.length = 0; leftHight = 0; rightHight = 0; } for (let i = 0, len = listData.length; i < len; i++) { let tmp = listData[i]; tmp.width = parseInt(tmp.width); tmp.height = parseInt(tmp.height); tmp.itemWidth = itemWidth let per = tmp.width / tmp.itemWidth; tmp.itemHeight = tmp.height / per; if (tmp.itemHeight > maxHeight) { tmp.itemHeight = maxHeight; } if (leftHight == rightHight) { leftList.push(tmp); leftHight = leftHight + tmp.itemHeight; } else if (leftHight < rightHight) { leftList.push(tmp); leftHight = leftHight + tmp.itemHeight; } else { rightList.push(tmp); rightHight = rightHight + tmp.itemHeight; } } this.setData({ leftList: leftList, rightList: rightList, }); }, } })
a. 注册自定义组件
在使用自定义组件的Page的json文件中声明要使用的组件
{ .... "usingComponents": { "waterFallView": "../../component/WaterFallView/WaterFallView" } }
b. 在 wxml 中添加组件,并加上 id
<waterFallView id='waterFallView'> </waterFallView> c. 在JS中找到组件,并调用fillData() 方法。下拉刷新时 isFull 传 true。 fillData: function (isFull,goods){ let view = this.selectComponent('#waterFallView'); view.fillData(isFull, goods); },
线上+线下+进销存+收银+会员门店零售管理好帮手
门店能实现快速收银,提升门店经营效率。
系统自带进销存管理,更好管理库存销售。
配备收银硬件一站式整体服务。
收 银 会员管理 库存管理 商品管理 交接班 数据报表 营销促单 售后处理 多种收款
获取报价1、本网站发布的该篇文章,目的在于分享电商知识及传递、交流相关电商信息,以便您学习或了解电商知识,请您不要用于其他用途;
2、该篇文章中所涉及的商标、标识的商品/服务并非来源于本网站,更非本网站提供,与本网站无关,系他人的商品或服务,本网站对于该类商标、标识不拥有任何权利;
3、本网站不对该篇文章中所涉及的商标、标识的商品/服务作任何明示或暗示的保证或担保;
4、本网站不对文章中所涉及的内容真实性、准确性、可靠性负责,仅系客观性描述,如您需要了解该类商品/服务详细的资讯,请您直接与该类商品/服务的提供者联系。
推荐文章
最新消息总结,开发一个小程序我们可以选择的第三方框架有5种,大家比较熟悉的有美团小程序框架mpvue,还有组件化框架等...
最近在调研小程序的分享能力,本篇文档主要是调研小程序关于分享方面的玩法,目的是学习小程序在项目应用以及玩法链上...
许多人在使用小程序,会有一个很麻烦的事情,就是使用过小程序之后,会不断的发送自己的定位消息,那么这个小程序的...
一款小程序,很多时候需要调用内置的照相机,实现拍照并图片上传,那么要如何实现呢?...
积分商城搭建百科 积分商城作为一种有效的用户运营和营销工具,在众多企业和平台中得到广泛应用。它不仅能够增强用户...
积分商城搭建策略百科 1. 积分商城搭建策略概述 积分商城作为一种常见的用户激励机制,在各类平台中发挥着重要作用。它...
积分商城搭建服务商百科 积分商城搭建服务商,是指那些专门为企业或机构提供搭建积分商城相关服务的专业机构。随着市...
积分商城平台搭建全解析 在数字化营销的浪潮中,积分商城平台已成为众多企业提升用户粘性、促进消费转化的重要工具。...
公众号积分商城搭建百科 在数字化营销蓬勃发展的当下,公众号积分商城已成为企业和品牌提升用户活跃度、增强用户粘性...
积分商城搭建流程全解析 在数字化营销浪潮中,积分商城已成为众多企业提升用户粘性、促进消费转化的得力工具。搭建一...