如何开发电商类小程序 Vol.3:数据加载和图文排版

爱范儿  •  扫码分享
我是创始人李岩:很抱歉!给自己产品做个广告,点击进来看看。  

这里是「电商类小程序实战教程」的第 3 篇文章。

上一期,知晓程序(微信号 zxcx0101)以爱范儿旗下的玩物志小程序为 Demo,介绍了商品列表的实现方法。

今天,我们将先完成上一期「加载更多列表」的功能,再来谈一谈 如何在商品详情页中,将商品描述从富文本数据转换成 JSON 数据后,并进行图文排版

「查看更多」功能

我们还是先来看一下效果图:

如何开发电商类小程序 Vol.3:数据加载和图文排版

1. 调用 Toast 提示

通过调用 wx.showToast()  ,可以实现上图中部的 Toast 提示(加载中)。

微信提供的 Toast 组件有  successloading  两种状态(旧版本的 loading 组件已经被废弃)。

				
					/***list.js***/
					wx.showToast({
					title: '成功', //提示的文字信息
					icon: 'success', //图标,只支持"success"、"loading"
					duration: 2000, //提示的延迟时间(毫秒),最大为10000
					success: function() {}, //调用成功的回调函数
					faile: function() {}, //调用失败的回调函数
					//接口调用结束的回调函数(调用成功、失败都会执行)
					complete: function() {}
					})
				
			

需要注意的是, showToast 执行时,整个页面是不可点击的。 所以,不用考虑用户意外触发多次「查看更多」的问题。

调用 wx.hideToast() 即可隐藏 Toast 提示框。

现在,我们来思考一个问题。上面说到 wx.showToastduration 最大值为 10000 毫秒,也就意味着 当请求时间大于 10 秒,若没有返回数据时, loading 提示框会自动消失

这会带来一些问题:

  • 「查看更多」按钮重新变回可点击状态,可能造成请求的重复提交。
  • 加载提示消失与数据成功加载之间出现时间差。

如何解决这个问题呢?其实很简单。

我们先给 loading 设置 10000 毫秒延迟时间,超过 10000 毫秒后,即使请求成功,也不保存任何数据。

同时,将按钮文字改回「查看更多」即可。

我们初始化一个 timeoutFlag 的对象,使用 timer = setTimeout() 设置 9800 毫秒延时。 9800 毫秒后,以 timerkey 设置一个对象 { isTimeout: true } ,每次发起请求时都会有一个 timer 作为标识。

若请求成功时 timeoutFlag.timer 的值为 { isTimeout: true } ,则不处理请求成功后的数据。

为什么要设置 9800 毫秒而不是 10000 毫秒呢?

那是因为 setTimeout 的计时并不准确,我们给出 200 毫秒的提前量,以防止代码出错。

我们来封装一个 _setTimeoutFlag 方法:

				
					/***list.js***/
					_setTimeoutFlag: function () {
					var that = this;
					var timer = null;
					timer = setTimeout(function () {
					that.setData({
					tipText: '查看更多'
					});
					timeoutFlag.timer = { isTimeout: true };
					}, 9800);
					timeoutFlag.timer = { isTimeout: false };
					return timer;
					}
				
			

2. 构建与实现  loadMore  函数

我们需要一个 loadMore 函数,来做到数据的分页查询。

一般,都是通过设置两个查询参数来控制,分别是每次请求条数 limit 和每次请求起始数 offset (即从第几条获取数据)。

以我们的需求为例:

  • 第一次获取 20 条: limit=20 & offset=0
  • 第二次再新增 10 条: limit=10 0& offset=20
  • 第三次再新增 10 条: limit=10 & offset=30

当然,根据各自不同的分页实现, limitoffset 的命名也不相同,我们只要了解原理即可。

根据以上逻辑,当用户点击「查看更多」按钮后,小程序在不同情况下应该给出相应的反应:

  • 按钮文字变为「正在加载…」,页面弹出「加载中…」的 loading 提示框,设置 offset + 10 并发起请求
  • 有新数据加载时,按钮文字变回「查看更多」,关闭 loading 提示框,保存当前 offset
  • 无新数据加载时,按钮文字变为「没有更多啦」,关闭 loading 提示框
  • 请求失败时,按钮文字变为「查看更多」,关闭 loading 提示框

先在 list.wxml 中设置按钮,并绑定点击事件 loadMore;

				
					/***list.wxml***/
					<view class="btn-load-more" bindtap="loadMore">
					{{ tipText }}
					</view>
				
			

根据上面的流程,我们来封装一下 _getProductListloadMore 方法。

				
					/***list.js***/
					loadMore: function () {
					var that = this;
					this.setData({
					tipText: '正在加载...'
					});
					wx.showToast({
					title: '加载中...',
					icon: 'loading',
					duration: 10000
					});
					var timer = that._setTimeoutFlag();
					this._getMoreProductList(timer);
					},
					_getMoreProductList: function (timer) {
					var that = this;
					wx.request({
					url: CONFIG.API_URL.PRODUCT_LIST + this.data.orderBy,
					method: 'GET',
					data: {
					limit: 10,
					offset: this.data.offset + 10,
					shelf__id: this.data.shelfId,
					img_size: 'small'
					},
					success: function (data) {
					if (!timeoutFlag.timer.isTimeout) {
					if (data.data.objects.length > 1) {
					var objects = that.data.productList
					.concat(data.data.objects);
					that.setData({
					productList: objects,
					offset: that.data.offset + 10,
					tipText: '查看更多'
					});
					} else {
					that.setData({
					tipText: '没有更多啦'
					});
					}
					}
					clearTimeout(timer);
					wx.hideToast();
					},
					fail: function () {
					that.setData({
					tipText: '查看更多'
					});
					wx.hideToast();
					}
					});
					}
				
			

至此,我们已经完整实现了商品列表页的开发,接下来进入商品详情页。

商品详情图文排版

在商品详情页中,我们主要来说一说图文排版的实现。

如何开发电商类小程序 Vol.3:数据加载和图文排版

目前商品详情的图文介绍,一般都是通过后台的富文本编辑器来排版创建的,数据都是以 HTML 代码的形式保存下来,然后在页面上直接渲染出来。

但是对于小程序来说, 这种 HTML 形式的数据不能直接拿来使用,因为小程序根本不能解析 HTML 代码

此时,我们需要处理由富文本编辑器所创建的数据,将其转换为 JSON 格式的数据,以便于在小程序里使用。

我们有两种思路去解决这个问题:

  1. 由前端去解析 html 格式的数据,用正则匹配 HTML 标签,然后转换成 JSON 数据;
  2. 交由后端去解析,同时新增一个专用的 API,返回解析过的 JSON 数据。

我们选用的是第二种方案,获取到的 JSON 数据格式如下:

				
					{
					"description": [
					{
					"content": "xxx.jpg",
					"type": "image"
					},
					{
					"content": "商品描述文字",
					"type": "text"
					}
					]
					}
				
			

我们只要将获取的数据用 wx:for 渲染出来,渲染时判断 type 选择对应的 textimage 组件即可。

				
					/***detail.wxml***/
					<block wx:for="{{ description }}">
					<view
					class="description-img"
					wx:if="{{ item.type == 'image' }}">
					<image
					class="description-img-content"
					src="{{ item.content }}">
					</image>
					</view>
					<view
					class="description-text"
					wx:elif="{{ item.type == 'text' }}">
					<text class="description-text-content">
					{{ item.content }}
					</text>
					</view>
					</block>
				
			

来看效果图:

如何开发电商类小程序 Vol.3:数据加载和图文排版

 

仔细观察一下,我们可以发现,每一张图片的宽高都发生了不同程度的裁剪、拉伸或压缩。

这是由于 image 组件的默认宽高导致的, 我们在第一期说过,要特别留意小程序内置组件的默认样式,它们很可能会引起各种各样的问题。

关注知晓程序(微信号 zxcx0101),回复「 电商 」,获取电商类小程序实战教程的往期文章。

我们的期望是,图片能够按照原有的宽高比例进行显示,并且每一张图片的宽度都能撑满整个内容区域。这应该如何处理呢?

这里就需要用到 image 组件的 load 事件,使用 bindload 属性将事件绑定在 image 组件中。

我们可以用 event.detail = {height:'图片高度px', width:'图片宽度px'} 的方式调整图片宽高尺寸。

我们定义一个 imageLoad 函数,作为 image 组件的 load 事件的处理函数,用 data-index 保存当前 wx:forindex 值作当前图片的索引值。

detail.wxml 改写 image 组件如下:

				
					<image
					class="description-img-content"
					src="{{ item.content }}"
					bindload="imageLoad"
					data-index="{{ index }}">
					</image>
				
			

detail.js 定义 imageLoad 函数如下:

				
					data: {
					images: {}
					},
					imageLoad: function (e) {
					var realityWidth = e.detail.width;    //获取图片实际宽度
					var realityHeight = e.detail.height;  //获取图片实际高度
					//获取图片的实际宽高比例
					var proportion = realityWidth / realityHeight;
					//设置图片的渲染宽度,750rpx - (2 * 40rpx) = 670rpx;
					//父元素的左右 padding 都是 40rpx
					var viewWidth = 670;
					//按比例计算出图片的渲染高度
					var viewHeight = 670 / proportion;
					var images = this.data.images;
					//将图片的 data-index 值作为 images 对象的 key
					//用来储存该图片的计算后的渲染宽高
					images[e.currentTarget.dataset.index] = {
					width: viewWidth,
					height: viewHeight
					};
					this.setData({
					images: images
					});
					}
				
			

此时,我们就可以在 image 组件中获取到 images[index].widthimages[index].height ,并通过设置行内的 style 给每一个图片设置宽高了。

detail.wxml 改写 image 组件如下:

				
					<image
					class="description-img-content"
					src="{{ item.content }}"
					bindload="imageLoad"
					data-index="{{ index }}"
					style="width:{{ images[index].width }}rpx;
					height:{{ images[index].height }}rpx">
					</image>
				
			

完成的效果图如下:

如何开发电商类小程序 Vol.3:数据加载和图文排版

本期内容总结

本期的「电商类小程序实战教程」就到这里了。

想跟本文作者在线交流小程序开发,关注微信号 zxcx0101,点击下方菜单栏「 加群交流 」即可。

最后,知晓程序(微信号 zxcx0101)来总结一下本期内容的重点:

Toast 提示:

  • Toast 提示可以使用 wx.showToast() 来调用,使用 wx.hideToast() 隐藏。
  • 开发者可以自定义 Toast 展示时间、展示文案等。
  • Toast 最长展示时间不能超过 10000 毫秒,开发者需要做好超时处理工作。

 图文排版:

  • 如果服务器中的数据是 HTML 数据,需要转换为 JSON,小程序才能解析。
  • 直接将图片进行排版,图片宽高会出现问题。开发者需要处理好图片的宽高问题。

在下一期中,我们会结合 navTab 和 tabBar 组件,来谈一谈自定义组件的实现方式,请大家继续关注知晓程序。

本文由知晓程序原创出品,关注微信号 zxcx0101,「 电商 」获取电商小程序实战指南的往期文章。

快速关注知晓程序↓↓↓

如何开发电商类小程序 Vol.3:数据加载和图文排版 知晓程序 微信号 zxcx0101) 是爱范儿旗下专注于小程序生态的公众号。我们提供最全面、新鲜的小程序资讯 消息、观点、指南、活动 和服务 ,在这里你 能了解到关于小程序的一切。

随意打赏

微信小程序 电商小程序 电商童装电商
提交建议
微信扫一扫,分享给好友吧。