小程序高级电商前端第2周深入理解REST API开发规范 开启三端分离编程之旅<一>----优惠券、函数式编程、重构Theme

优惠券的一些基本概念:

在上一次小程序高级电商前端第1周走进Web全栈工程师<四>----自定义组件与Lin UI的小试牛刀已经使用Lin-UI完成了商品类别的展示,接下来则来实现它了:

在正式实现之前,先来对“优惠券”的一些基本概念有一个大致的了解,这个很容易理解呀,就是在买商品的时候可以拿它来抵钱进行消费嘛,是的,但是从优惠券的设计实现角度的话还是相当复杂的,当然主要是体现在服务端,由于咱们学习的目标是全栈,所以就不区分前端和后端了,提前多了解一些有益无害,主要说明如下几点:

1、优惠券它本身是分类型的,比如:满减、折扣。另外它使用的话也是有条件的:比如该券是否是全场券,还是说该券只能使用在某种商品分类下。

2、对于前端来说还需要判断优惠券的过期时间,而这个过期时间有可能是固定一个周期来使用,也有可能是当用户领了之后才开始核算有效期,多少天之后该券则失效之类的。

3、优惠券的领取和使用是两个完全不同的概述,切记不要混为一谈了,这个在之后再来体会。

4、所有的优惠券是通过活动来下发给用户的,也叫优惠券活动,一般有这在个信息:start_time、end_time,另外活动是可以动态上下架的,所以还需要有一个online是否在线的属性。

5、对于优惠券还需要有一些状态管理,如领取状态、是否使用、是否过期。

优惠券入口:

api:

如上面理论描述,这里的优惠券其实是以活动的形式来发放的,所以上官网3. API清单 | Lin Books查看一下API文档:

其实还有另一个类似的API:

很明显对于首页优惠券入口只需要显示入口图片既可,所以调用第一个不包含优惠券活动的API就可以了。

新建model:

其方法命名为啥叫getHomeLocationD呢?这块在之前有解释过,因为我们要获取的这个优惠券位于首页页面的第D个位置,所以就这么一种约定来命名啦。说到这块的命名,咱们目前有一处不太规范的地方正好将其改正了:

在IDE中重命名很简单,如下:

 很顺其自然的操作对吧,但是!!!在js中,当你的代码足够复杂之后,这样的重命名可能会改错,也就是不该改的地方也改了,但是如果用java的话这样改是一点问题都不会有,因为可能用反射精准的帮你全部改正确,所以这一点需要知道,有这种风险存在。

发起http请求:

import {Http} from "../utils/http";

class Activity {
    static locationD = 'a-2'

    static async getHomeLocationD() {
        return await Http.request({
            url: `activity/name/${Activity.locationD}`
        })
    }
}

export {
    Activity
}

其中注意一个细节:

这里暂且这么滴,接着在home.js中调用一下:

mock数据准备一下:

{
    "id": 2,
    "title": "夏日好礼送不停",
    "entrance_img": "http://i2.sleeve.talelin.com/m14.png",
    "online": true,
    "remark": "限服装、鞋、文具等商品",
    "start_time": null,
    "end_time": null
}

界面图片显示:

此时回到home.wxml中:

此时运行看一下效果:

背景颜色到底怎么设置?

不过跟预期的效果还是有一些差别,第一是优惠券入口跟上面的分类是有一个间距的,这个比较容易,加一下margin就可以了:

但是!!!跟预期效果还是有区别的:

对于这个间距的实现有两个思路:

1、这个间距用view来实现,然后给它设置成一个灰色背景,很显然这种方式最low,是最不值得推荐的,因为列表的其它块也有类似的间距。

2、让整个页面弄成灰底,这是推荐的。

方式一:只针对home页面进行单独设置

这里要注意了,别小看了这个背景的设置,其实它的坑还是不少的,先来上微信开放文档中找到页面配置中设置背景颜色相关的属性:

这里为了看得比较明显,先设置成一个纯黑背景色,但是你会看到看不到效果,这是因为需要将它部署在真机上然后有下拉刷新效果时才能看到,这里截个图,大概这个背景色会体现在这里:

很显然目前这种方式达不到我们的要求,所以先把这个配置给去掉,再来想其它办法,第二个办法就是对home页面的根view元素进行背景色设定,如下:

运行背景色确实是有了,但你会发现好多问题:

下面一个个来进行解决,通过解决这些问题也能收获很多。

1、顶部多出来一个间隔:

这个坑非常不好找,原因是我们在新建小程序工程时微信就内置了container这样名称的样式,如下:

所以咱们将微信内置的这个css样式给去掉就好了,再预览效果:

2、为啥顶部主题与banner之间多出来一个间距?

看图说话:

这是因为小程序的图片标签会自带一个间距,解决的话,需要这样:

此时再来看一下间距就消除了:

3、分类六宫格整体为啥都黑了?

如上图也可以发现,咱们的分类宫格全黑了,是因为默认情况下此控件的背景是透明的,所以这里回到宫格组件下将其背景设置成白色既可:

此时再运行:

4、消除优惠券的底部间距:

同样的,对image添加一个这个属性既可:

运行:

但是你会看到优惠券底部还是有一些小黑背景,这个就跟图片的资源有关了,不影响大局先忽略了。 

至此就达到了我们想要的灰间距的目的了,但是!!!有以下几个缺点:

  • 需要每个页面都要设置背景,达不到一个全局化的配置;
  • 只有内容区域设置了背景,全局页面木有。
    这是啥意思呢?咱们切换一下iphone的机型预览,换分辨率更大一点的,就能看出来了:

方式二:全局背景设置

基于上面方式一的缺点,接下来再来寻找更优的一种设置全局背景的方法,先来将我们给home内容区域设置的背景色给去掉:

然后全局页面的背景色如何设置呢?其思路也很简单,就是找到一个rootView,像android中的每个页面的rootView不是一个DectorView么?同样的思路,这里需要使用到小程序工具上的这个界面来寻找rootView:

所以,咱们就可以针对这个page元素进行背景色的设置了,如下:

此时再来看效果:

嗯,完美,此时把背景色改为正常的灰色就可以了,如下:

此时整体再瞅一眼效果:

页面到底是否应该合并HTTP请求?

每周上新效果概述:

接下来则需要来实现每周上新了:

而它是属于一个主题,在之前咱们已经用过一个主题了:

准备API:

那先来准备请求这个主题的方法:

思考接口合并的场景:

在继续往下编写之前,这里思考一下,对于首页列表可能会有多个主题的数据要获取,针对这种场景其实存在一个接口合并粒度的问题,主要是有如下几种做法:

1、每一个主题的数据都发送一个http;

2、整个Home页面只发送一个http,然后一次性下发所有的数据;

3、有选择的把部分http请求合并成一个;

其实参考的指标主要是从以下几个角度来思考:

a、HTTP的请求数量;

b、HTTP会涉及到多少次的数据库查询;

c、接口的灵活性,接口的可维护性;

下面则分上面三个场景来分析一下:

1、每一个主题的数据都发送一个http;

  • a、HTTP的请求数量;【很多】
  • b、HTTP会涉及到多少次的数据库查询;【很多】
  • c、接口的灵活性,接口的可维护性;【很灵活】

2、整个Home页面只发送一个http,然后一次性下发所有的数据;

  • a、HTTP的请求数量;【只有一次,性能好 】
  • b、HTTP会涉及到多少次的数据库查询;【一次http只会涉及到一次查询,而且不会重复】
  • c、接口的灵活性,接口的可维护性;【灵活性最差】

3、有选择的把部分http请求合并成一个;

  • a、HTTP的请求数量;【会相应减少】
  • b、HTTP会涉及到多少次的数据库查询;【会相应减少】
  • c、接口的灵活性,接口的可维护性;【这个得看怎么合】

其中把哪些接口合并成一个呢?其主要考虑的指标是它:

也就是看接口合并之后,能给服务器减少多少次的数据库查询,回到咱们的主题的接口来看,很显然可以通过一条SQL就可以查出所有的主题来对吧,所以是非常适合进行合并的。那为啥在做接口合并时主要看“b、HTTP会涉及到多少次的数据库查询;”这个指标呢?因为Web应用里最耗性能的就是IO,也就是属于IO密集型,与之对应的还有一个CPU密集型,像音视频的编解码之类的就是属于这种的,这块大致了解一下。

函数式编程概述:

更改获取多个主题的方法:

基于上面所分析的,咱们需要将主题获取的的逻辑更改一下,如下:

import {Http} from "../utils/http";

class Theme {
    static locationA = 't-1'
    static locationE = 't-2'
    static locationF = 't-3'
    static locationH = 't-4'

    static async getThemes() {
        const names = `${Theme.locationA},${Theme.locationE},${Theme.locationF},${Theme.locationH}`
        this.themes = await Http.request({
            url: `theme/by/names`,
            data: {
                names
            }
        })
    }
}

export {
    Theme
}

由于首页还有其它的一些主题,这里一次性的全定义了。

home.js中getHomeLocationA()逻辑进行修改:

接下来则回到home.js中调用一下获取所有主题的API:

接下来则需要从所有主题中找到对应主题的数据,这里当然可以进行json数组遍历来找,但是更好的一种方式是使用函数式编程,类似于Java8中Stream相关的遍历过滤集合的操作,具体如下:

此时这里有两个小细节待优化:

而关于==和===的区别可以参考一下它:js中==和===区别 - 果感 - 博客园

另外还有一个细节:

改为:

类可以保存数据,但对象可以保存状态:

目前咱们的代码还是不够优,先来看一下代码:

 其实这些常量已经在Theme已经定义过了:

另外对于调用方还需要知道每一个theme数据获取的条件细节,这块很明显可以用面向对象的思路来对其进行封装一下,另外关于面向对象这里先抛出一句话:“类和对象本身就具有保存数据的功能,其中类能保存数据,但是不能保存状态;类的对象是既能保存数据又能保存状态”,怎么来理解呢?举例说明一下:

static的这些变量可以看到肯定是类具备保存数据的功能的,但是它能保存状态么?很显然是不行的,因为说到状态肯定是该属性是能变的,而如果像这样:

很显然类的对象是保存状态了,因为不同的对象,同样的 属性保存了2个数据的状态, 那对比一下类,为啥它就不能保存状态呢?看下面的代码:

请问一下此时a的值能同时保存1和2么?很显然只能保存2,所以类是可以保存数据,但是不能保存状态的。

重构Theme:

接下来就可以用面向对象的思想对咱们的Theme的数据获取这块给重构一下了,如下:

import {Http} from "../utils/http";

class Theme {
    static locationA = 't-1'
    static locationE = 't-2'
    static locationF = 't-3'
    static locationH = 't-4'

    themes = []

    async getThemes() {
        const names = `${Theme.locationA},${Theme.locationE},${Theme.locationF},${Theme.locationH}`
        this.themes = await Http.request({
            url: `theme/by/names`,
            data: {
                names
            }
        })
    }

    getHomeLocationA() {
        return this.themes.find(t => t.name === Theme.locationA)
    }

    getHomeLocationE() {
        return this.themes.find(t => t.name === Theme.locationE)
    }

    getHomeLocationF() {
        return this.themes.find(t => t.name === Theme.locationF)
    }

    getHomeLocationH() {
        return this.themes.find(t => t.name === Theme.locationH)
    }

}

export {
    Theme
}

其中对于Theme对象,只需要请求一次服务器之后再拿各个主题都是从缓存中拿了?所以调用方也作相应的调整:

准备Mock数据:

在运行之前记得先准备mock数据:

[
    {
        "id": 1, 
        "title": "清凉一夏,折扣季", 
        "description": "秋天是金色的。麦穗是金色的,秋阳是金色的。虽然冬快至,但宜人的温度总是让我们心情愉快#我们为您精选了一系列秋冬折扣商品,慢慢挑选吧~", 
        "name": "t-1", 
        "entrance_img": "http://i2.sleeve.talelin.com/m2.png", 
        "extend": null, 
        "internal_top_img": "http://i2.sleeve.talelin.com/m33.png", 
        "title_img": "", 
        "tpl_name": "janna", 
        "online": true
    }, 
    {
        "id": 5, 
        "title": "风袖甄选", 
        "description": "甄选", 
        "name": "t-3", 
        "entrance_img": "http://i2.sleeve.talelin.com/m9.png", 
        "extend": null, 
        "internal_top_img": "http://i2.sleeve.talelin.com/m11.png", 
        "title_img": "", 
        "tpl_name": "diana", 
        "online": true
    }, 
    {
        "id": 6, 
        "title": "时尚穿搭", 
        "description": "帅点才有女朋友", 
        "name": "t-4", 
        "entrance_img": "http://i2.sleeve.talelin.com/m10.png", 
        "extend": null, 
        "internal_top_img": "http://i2.sleeve.talelin.com/m12.png", 
        "title_img": "", 
        "tpl_name": "irelia", 
        "online": true
    }
]

然后将此json替换到原mock接口中返回值中既可:

关注个人公众号,获得实时推送

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

webor2006

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值