艺灵设计

全部文章
×

复盘自己在开发生鲜类小程序时犯下的几个错

作者:艺灵设计 - 来源:http://www.yilingsj.com - 发布时间:2020-10-01 20:06:44 - 阅: - 评:0 - 积分:0

摘要:万万没想到,为了开发一款生鲜类的小程序,我竟然用了两个半月的时间!现在再回顾这两个多月,我走了不少弯路也犯了不少错。由于一直没太多的时间,所以网站的周新也断了。趁国庆期间,今日来复盘一下此次开发中遇到的坑及一此问题......

背景:6月底,我接到一个开发微信小程序的任务。当时凯哥跟我简单的过了下逻辑,对于做过好几个小程序的我来说,我并没有在意这个小程序(指重视程序,不过120+个页面的小程序对于我来说还是头一回遇到),这也就为后面自己犯错埋下了伏笔......

一、最主要的错误:在没有完全理解透业务前就开始撸代码

一直以来,这个缺点都伴随着我。由于我平时的工作基本不会过多参与业务逻辑,这也就导致自己一直都不太了解业务。由于不了解业务,每次开发的产品我都只能停留在表现层。像这次的“鲜德小程序”,我在开发了一个月的时候还不知道这个小程序有啥亮点。直到在第二个月开发“发现”版块时,凯哥单独跟我讲了一会儿后,我突然眼前一亮,此时发现了这个小程序的亮点。也就是这个时候,我突然觉得这个小程序变得棘手起来。因为“发现”版块不是独立的,会跟“商家”有交集。而“商家主页”看似是一个像点外卖的界面,但实际上又分三大种不同的场景。分别是:
普通商品加购
菜谱加购(一道菜会有多个食材,也就是批量加购)
提前购(最多可提前一周预订一日三餐的食材)
由于有“提前购"又是一直超前预订的概念,所以页面的耦合程度也越来越高,反正我自己是有点儿头晕,不知道用户使用时会不会因为同一页面在不同的入口进入后有着不同的逻辑而误以为这是bug......

二、第二个错误:考虑问题片面,对突如其来的idea没有全局把控性

刚开始时,凯哥给我灌输了一套组件化开发的理念,这个理念大致是:前端搞个组件库,后端接口来实现页面的动态化。比如:首页现在有5个模块,我想动态添加2个,另一个页面也可以使用首页中的几个模块或者C页面中的几个模块。前端不需要改页面,后端接口来控制这些模块的动态操作......

这个想法听起来很好,个人感觉非常像saas平台的功能。虽然常规的开发中,组件是必不可少的,但基本上都是哪个页面需要用哪些组件是写死的,无法做到想象中的这样灵活。那有没有方法实现呢?其实是有的,无非就是事先写一套组件库,全部放一个模板页中,然后需要动态化模板的页面就引用这个模板页就行了。代码大致如图:把所有组件放到一个模板文件中.png把所有组件放到一个模板文件中

虽然初步实现了需求,但随着页面的开发,你会发现这种想法压根就不现实!除非该模块是静态的或没有过多交互的,否则很难处理js交互逻辑及事件。要么就是把js逻辑也放到这个组件中,这样的话就需要再造出大量的组件来......

关于这种需求,让我想起了上上家的数式科技。当时我们也是搞组件化,用一套DSL规范来实现兼容多端且可以配置js逻辑。然后我就经常听到一些专业术语:一对一、一对多、多对一、多对多、模块、模型、DSL ......

所以看官应该能猜到,后面我主动放弃了这种组件化的开发理念。页面需要啥组件了,老老实实的引用并在该页面写对应的js逻辑好了。

三、第三个错误:过于纠结用户体验和功能实现,无法正确取舍

这个缺点也一直影响着我,导致我经常会花费大量的时间做一些优化反而吃力不讨好。现在再看看这个小程序,如果让我从头再做一遍,根本用不了两个半月的时间。该存储的数据缓存起来,该后端提供的接口让后端提供,前端不应过多依赖且相信缓存数据,有些极端操作就没必要考虑了......

但事情已经发生了,那就来说说吧。干这行的,应该不止一人会像我这样,在某些时候会陷入一种“死循环”的模式,然后越陷越深......

说起购物车功能,一般的电商类小程序都有它的身影。对于我们的“鲜德小程序”,购物车功能也是有的,而且还不止一处哦~!看官可以先体验下竞品,比如:叮咚买菜京东到家这两款微信小程序和对应的App。体验过后有兴趣的可以再体验下鲜德小程序(因某些原因,可能国庆后会上线,看官可以先插个眼~),感受一下其逻辑的复杂吧!

我花了很长时间来处理购物车的逻辑,并不是为了计算价格、也不是为了计算数量而是仅仅为了计算商品的勾选状态!因为商品的添加、减少都会发送接口来请求数据,唯独这个勾选状态是没有接口的。说到这里,一般有三种解决方案,见下方表格。

三种方法优缺点对比
方法优点缺点
法一:前端不存储简单,省事若用户切换到其他页面后再进入时,勾选状态没有了,用户体验极差。
法二:前端存储解决了法一的缺点,用户再次进入页面时,勾选状态保留,用户体验较好。1、难度受数据复杂程度、出现频率、场景不同等因素影响;
2、用户换设备后存储丢失;
3、用户清缓存后数据丢失;
4、token过期或手动退出后换帐号进来时,若缓存处理不当可能会出现数据串号的现象。
法三:后端存储1、解决法二的缺点;
2、前端无需考虑复杂逻辑花费大量的时间来设计存储的逻辑代码。
1、每次操作多了一个请求,加大服务器的压力;
2、至于后端,我就不知道了

由于后端老哥说后端存储麻烦,要改的东西多,我就只能搞前端存储了。于是,我开始了漫长的踩坑之路......

3.1、程序设计

由于小程序中有不同的商家,所以我在经过多次改版后决定以商家id为key来直接存储商品数据,数据的勾选改用添加一个checked属性来判断,最终的代码大致如下:

  1. {
  2.   "1": [ /* 店铺id为1 */
  3.     { "id": 66, "cart_num": 1, ..., "checked": true },
  4.     { "id": 67, "cart_num": 5, ..., "checked": false }
  5.   ],
  6.   "3": [ /* 店铺id为3 */
  7.     { "id": 88, "cart_num": 0, ..., "checked": false },
  8.     { "id": 66, "cart_num": 66, ..., "checked": false }
  9.   ]
  10. }

别问为什么非要以店铺id为key,问就是如下:
1、在某个店铺主页时可根据key快速取出对应的加购数据;
2、清空购物车时也挺方便的,直接把店铺置空或干掉就行。

既然设计存储的格式已经有了,那问题是不是就很简单了呢?显然,实际上并没有这么轻松。

3.2、捋捋有哪些页面存在加购的情况吧

我捋了一下,一共有7~8个页面,捋完后我懵了,怎么这么多!它们分别是:
首页、新人专享页、商品分类页、商家主页、商家详情页、购物车页面、退款页面、菜谱详情页
考虑到降低商家的损失,所以最后退款页面的可以先忽略,剩下还有7个不同的页面。如图:商家首页.png商家首页
商品详情页.png商品详情页
在上面提到的6个页面中,直接显示勾选状态的有三个页面,分别是:
商家主页、商品详情页、购物车页面
既然如此,那其他页面中是不是不用处理了呢?显然不是。

举个例子:用户在商品详情页时购物车中有5件不同的商品,用户取消了5件勾选,用户到首页又添加了2件新商品和1件已经存在购物车中的商品。问:此时购物车中勾选商品的有几件?

所以,即使其他页面没有明确显示那个勾选的按钮,但只要有加购的功能,前端都需要做存储检验呀!而这套规范代码放到什么位置也是一个难题。直接放到请求购物车的接口中吗?但不同页面需要处理的数据又不同且增加、减少、勾选、全选、清空这些操作时也需要跟封装的这个方法有所交互,否则就会出现数据不同步或数据不对的现象。尽管uni.setStorageSync()可以实现存储,但这个操作无法做到动态响应,于是我又配合vuex来实现数据动态响应......

此时,我的逻辑已经有点儿复杂了,但更恶心、更让人抓狂的即将来临!

3.3、进一步分析商家主页的功能

来爆下商家主页的美照,如图:商家首页高清图.png商家首页高清图正常情况下,看官应该发现不了什么大的问题,下面做下文字说明。

说明
功能说明
买菜这里展示菜品,加购时只能1件1件的添加
菜谱这里展示的是菜谱,一道菜有多个食材。
言外之意:加购菜谱时可能会添加若干个食材到购物车中。
底部弹窗虽然这里展示的是加购的东东,但也是可以进行加、减、勾选、清空操作的哈。

发现问题了没有?添加菜谱时不再是单一的一对一操作了,而是变成了一对多的操作!那么此时再存储就又分三种情况。

添加菜谱时分三种情况
情况类型解决方案
菜谱需要的食材完全不在购物车中在循环时判断,直接push即可
菜谱需要的食材完全在购物车中在循环时判断,更新对应商品的数量及checked状态
菜谱需要的食材部分不在购物车中需要考虑前两者,做出兼容处理

这仅仅是存储工作,页面还需要更新呀。用户在点击了主页中的商品时,被点击的商品数量会发生变化,对应的底部弹窗中的商品也需要发生变化。

由于页面中有多个组件且数据是由不同的接口返回的,所以动态更新的操作也变得麻烦起来。这里最简单的方法就是:每次操作直接请求后端接口,但这样一次操作就会请求3~4个接口(商品数量变化的接口、商品详情页的接口、相关推荐商品的接口、底部购物车列表的接口),显然是不合理的。那怎么办呢?还能怎么办,后面三个接口不发送请求,我自己通过第一个接口来进行循环查找更新呗......

3.4、终级噩梦:提前购

如果看官觉得目前为止不算什么,可以继续向下看。等到处理提前购的时候,我彻底崩溃了,因为这个逻辑里面又引出很多新的问题。他的逻辑是这样的:
入口:底部tabBar中点发现 - 进入后点提前购 - 进入选择日期页面 - 进入选择三餐时间页面 - 进入提前购页面;
选择三餐:每餐首次会跳转到发现页面 - 点菜谱进详情 - 打包 - 跳转到提前购;
三餐追加:食材时会跳转到商家主页,打包后跳回到提前购页面。

当用户跳转到发现页面后,除了直接点展示的菜谱外,可能通过搜索的方式进行先搜索,当用户跳转到商家主页时,除了在列表页可选择外,在详情页也是可以选择的。基本上这就是一个无限循环的操作,直接提交订单那一刻,整个提前购的链路算是结束了。

链路本来是没什么问题的,我只需要处理好链路上的逻辑就行了。但由于发现页面是在tabBar中,所以在跳转到这个页面后,用户无法直接返回上一页。这是微信小程序的规定,我控制不了的,但凯哥说这个操作不合理,然后他出了一个主意:把发现页面复制一个,用户从提前购过来时直接跳转到这个复制的页面上,这样就可以返回到上一页了。

当时我一听,有道理啊!于是我就复制了一份,此时就再次暴露出前面提到的第二个错误:考虑问题片面,对突如其来的idea没有全局把控性

刚说了复制一个页面,然后我在选购时发现跳转几次后就无法跳转了,点击页面上的任何商品或js事件时全都无效!当时我还挺懵的,网上一查才知道,原来是页面栈已经达到了上限10层时会出现这种情况。然后我在控制台输入:getCurrentPages()输出数组长度就是10。此时就出现了页面栈上限的坑,简直了......

那怎么办呢?我又开始了新的填坑之路

页面跳转的方式
方法说明后退发生什么
wx.navigateTo()保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面。使用 wx.navigateBack 可以返回到原页面。小程序中页面栈最多十层。举例:
当前页面栈是:[a,b,c]对应的三个页面,
后退后是:[a,b];
所以,后退会正常返回到上一页
wx.redirectTo()该操作会关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面。相当于页面栈数量不变。举例:
当前页面栈是:[a,b,c]对应的三个页面,
现在要跳转到d页面,
普通方式跳转后的结果是:[a,b,c,d];
通过redirectTo()跳转后是:[a,b,d];
此时再后退无法退到上一页而是退到原页面栈的上上页b
wx.reLaunch()该操作会关闭所有页面并跳转到新页面,显然更不能使了。举例:
当前页面栈是:[a,b,c]对应的三个页面,
现在要跳转到d页面,
reLaunch()跳转后是:[d];
此时再后退会退出小程序
wx.navigateBack()该操作会关闭当前页面,返回上一页面或多级页面。该方式对非页面栈中的页面无效。

综合考虑了下发现:单独使用其中一个是无法解决问题的,所以我又封装了一个名叫linkJump的方法来实现跳转。其原理就是:
1、先拦截要跳转的页面,截取参数前的部分,
2、然后去判断否在tabBar中,若是则使用switchTab;若页面栈中没有当前链接,则使用navigateTo;若页面栈中有当前链接只是参数不同时,则使用navigateBack进行回退;
3、由于navigateBack无法带参数,所以在跳转前要先存储链接中的参数到本地缓存或vuex中。在跳转后对应的页面获取参数并更新数据,这样就解决了页面栈超过10级的方法了。详情见后续文章:《uni-app跨端开发微信小程序之页面栈超过10级的解决方法(先插个眼,文章晚点更新)

页面栈的问题是解决了,但链路太长有些操作我还是要放缓存中并和页面有交互。如果此时用户手动退出了帐号或token过期了,换个帐号进来,提前购的链路就中断了。因为我清除了缓存,用户进来时我又获取不到提前购的状态,用户只有重新操作了......

......

四、最后

这一路走来,踩了很多坑。说多了都是泪,一个个坑都是靠加班换来的。今天就不多说了,后续会针对性的写一些有关uni-app开发的相关笔记,有兴趣的看官可以留意下。最后,祝各位看官中秋、国庆双节快乐!

转载声明:
  若亲想转载本文到其它平台,请务必保留本文出处!
本文链接:http://www.yilingsj.com/xwzj/2020-10-01/uni-app-mistakes-made.html

若亲不想直保留地址,含蓄保留也行。艺灵不想再看到有人拿我的技术文章到他的地盘或者是其它平台做教(装)程(B)而不留下我的痕迹。文章你可以随便转载,随便修改,但请尊重艺灵的劳动成果!谢谢理解。

亲,扫个码支持一下艺灵呗~
如果您觉得本文的内容对您有所帮助,您可以用支付宝打赏下艺灵哦!

Tag: uni-app 微信小程序 跨端开发 生鲜小程序 私域流量 电商小程序 h5开发 购物车组件 组件化开发 DSL switchTab 页面栈

上一篇: @vue/cli3+typescript项目实战之二级导航菜单的实现及潜在的坑   下一篇: 返回列表

评论区