H5开发移动应用APP(店铺系列一)
首先,这是个真实的案例,我大兄弟在深圳开汽修店铺,但需要系统来管理日常经营活动,这正不是我擅长的吗?
说干就干,直接后端+web端+移动端来一套,于是紧急赶工,起早摸黑,产出约3万行总量代码,此系统与工作无关,
纯属个人业余开发,所以我敢拿来任意剖析,如果有时间我就出个连载,做一些典型的技术解析。这次说下移动端开发,
考虑到适配和多端问题,还有效率原因,我选择了混合模式,即原生做壳,H5+CSS做内容展现,JS代码实现逻辑,
然后用第三方工具打包生成移动App,我们来看下懒加载模式。
准备:
Idea2019.03/Gradle6.0.1/JDK11.0.4/Lombok0.28/SpringBoot2.2.4RELEASE/mybatisPlus3.3.0/Soul2.1.2/Dubbo2.7.5
/Mysql8.0.11/Vue2.5/OSS/Hbuilder2.6.1
难度: 新手--战士--老兵--大师
目标:
1.前端展现数据懒加载实现
步骤:
为了遇见各种问题,同时保持时效性,我尽量使用最新的软件版本。代码地址:https://github.com/xiexiaobiao/vehicle-shop-mobile.git
1 本套系统大体情况
后端代码量约1.5万,双前端约1.5万,技术还是很具代表性的,不然就不好意思拿出来说事了,详细可看Git库说明,下图是后端代码量分析:
Web管理界面:
手机端:使用Hbuilder编码,Uniapp框架,再随手捡了几个UI拿来大改了几下,基本形状如下:
2 数据懒加载
比如上图中商品页和订单列表页,数据流量还是很大的,因为里面参杂了图片,如果一上来就一股脑全加载,再搞个前端缓存假分页加载,那你得考虑下用户的
感受!因此需要懒加载,或者叫渐进式加载,必须得结合后端物理分页实现。
思路:后端物理分页,前端首次进页面,先请求一次后端并加载到页面,后续操作中页面滑到底后自动触发后续加载并请求后端,将返回数据累加到前端缓存数组,
再加载到页面,直到数据全部完毕。
首先定义后端(有点不规范,把数据处理写在controller层,没来得及优化):
com.biao.shop.stock.controller.ShopItemController
:
@GetMapping("/item/list")
public ObjectResponse<Page<ShopItemEntityDto>> listItem(@RequestParam("pageNum") int current, @RequestParam("pageSize")int size,
@RequestParam(value = "itemName",required = false) String itemName,
@RequestParam(value = "itemUuid",required = false)String itemUuid,
@RequestParam(value = "category",required = false) String category,
@RequestParam(value = "brandName",required = false)String brandName,
@RequestParam(value = "shipment",required = false) Integer shipment){
int shipmentTemp = Objects.isNull(shipment)? 2: shipment;
// 这里的shipment最好设计为int,可以接收 0 1 2 ,boolean型,只能是0 1,前端传来都会自带默认0,导致无法查询无此条件限制的
Page<ShopItemEntityDto> pageInfo = shopItemService.listItem(current,size,itemName,itemUuid,category,brandName,shipmentTemp);
ObjectResponse<Page<ShopItemEntityDto>> response = new ObjectResponse<>();
response.setCode(RespStatusEnum.SUCCESS.getCode());
response.setMessage(RespStatusEnum.SUCCESS.getMessage());
response.setData(pageInfo);
return response;
}
以上代码是controller层,具体后端服务实现我就省略了,请看Git源码,返回给web端是个简单的统一返回封装,
ObjectResponse{"code":200,"message":"SUCCESS","data":{Object}},其数据就是Page类型,具体是MybatisPlus中的
com.baomidou.mybatisplus.core.metadata.Ipage, 包含了数据总量,当前页数和每页的量,来个例子就是下面这样的:
{"code":200,"message":"SUCCESS","data":{"records":[{"idItem":2,"itemUuid":"SP000011","category":"修理","classification":null,"itemName":"雨刮器","sellPrice":60.99,"purchasePrice":45.99,"brandName":"奔驰系列","description":"奔驰系列","shipment":null,"alertQuantity":5,"specification":"35*35cm","unit":"支","picAddr":"https://biao-aliyun-oss-pic-bucket.oss-cn-shenzhen.aliyuncs.com/images/logo-samll.png","stock":null,"sales":null,"discountPrice":null}],"total":23,"size":500,"current":1,"orders":[],"searchCount":true,"pages":1}
那前端就是先定义一个初始请求的量,初始页值必须为 1,然后是每次懒加载的页面数据量,这里有个很隐蔽的地方,
必须保证首次懒加载的页面数据量填满屏幕,否则无法触发屏幕触底上滑加载:
pages\product\list.vue文件
data() {
return {
// 分页实现页面懒加载
pageInfo:{
"total": 0,
"size": 6, // 每次懒加载的页面数据量
"current":1// 首次请求的初始页值,之后每请求一次就累加 1
},
...
}
每次请求数据的方法封装一下:
requesForData:function(){
Request().request({
url:'stock/vehicle/stock/item/list',
method: 'get',
header:{},
params: {
'pageNum': this.pageInfo.current,
'pageSize': this.pageInfo.size,
},
}
).then(
res => {
let pdtArr = res.data.records;
this.goodsList = this.goodsList.concat(pdtArr);
// 懒加载机制 --> 加载一次后累加页数
this.pageInfo.total = res.data.total;
this.pageInfo.current += 1;
}
).catch(err => {
console.error('is catch', err)
this.err = err;
});
以上代码中,要实现懒加载机制,需每次加载一次后累加当前页数,另外使用Array.concat函数,追加到已有的数组后面,这样懒加载基本就成型了!
3 如何触发每次的懒加载?
方法一:uniapp页面有个自带的钩子:
//加载更多
onReachBottom(){
console.log("onReachBottom")
this.loadData();
},
方法二:页面模板中的scroll-view元素,加上@scrolltolower事件函数:
<scroll-view
class="list-scroll-content"
scroll-y
@scrolltolower="loadData"
:refresher-enabled = "false"
>
同时配合:
<uni-load-more :status="tabItem.loadingType"></uni-load-more>
当然,必须有个指示器,告知数据是否全部完毕了, 在loadData方法中最后加一个判断:
//判断是否还有数据, 有改为 more, 没有改为noMore
if(this.pageInfo.total > (this.pageInfo.current-1) * this.pageInfo.size){
navItem.loadingType = 'more';
}elseif(this.pageInfo.total <= (this.pageInfo.current-1) * this.pageInfo.size){
navItem.loadingType = 'noMore';
}
收工结束!
后记:
- 懒加载必须配合后端的物理分页机制实现,
- 避免数据前端过滤后导致页面数据没法到达屏幕底部,结果全部数据完毕还没完,但已有的数据却不满一屏,这就不能自动触发事件了!所以,必须禁止懒加载模式下前端数据过滤,即带条件后端查数据,
- 数据加载,要注意与页面渲染的前后顺序,不然页面元素都渲染完了,你数据还没来就尴尬了,上面的后端数据请求可以看到,现在axios都是异步的,返回Promise对象,目前最新的解决办法就是可以使用 async / await 来保证异步代码的执行顺序,但是一定注意 await 后必须是返回Promise对象,否则不保证代码顺序!如果出现页面加载完了,数据还没出来,可以多写几个console.log(),看是否页面渲染在前,数据返回在后。
- 不要看上面我只说了很少,这只是核心和思路,具体实现还是要费点心思的。
全文完!
我的其他文章:
- 1 阿里云平台OSS对象存储
- 2 Dubbo学习系列之十七(微服务Soul网关)
- 3 Docker部署RocketMQ
- 4 流式计算(五)-Flink 计算模型
- 5 流式计算(四)-Flink Stream API 篇二
只写原创,敬请关注
H5开发移动应用APP(店铺系列一)的更多相关文章
- Anyoffice -HTML5大赛 悦心(基于H5开发安卓音乐app)-项目总结
项目在线演示地址:http://rose111.applinzi.com/ github 地址:欢迎star https://github.com/midoxinxin/YueX-Music 悦心,一 ...
- MUI框架开发HTML5手机APP(一)--搭建第一个手机APP
前 言 JRedu 随着HTML5的不断发展,移动开发成为主流趋势!越来越多的公司开始选择使用HTML5开发手机APP,而随着手机硬件设备配置的不断提升,各种开发框架的不断优化,也使着H5开发的 ...
- MUI框架开发HTML5手机APP(一)--搭建第一个手机APP(转)
出处:http://www.cnblogs.com/jerehedu/p/7832808.html 前 言 JRedu 随着HTML5的不断发展,移动开发成为主流趋势!越来越多的公司开始选择使用H ...
- MUI框架开发HTML5手机APP
出处:http://www.cnblogs.com/jerehedu/p/7832808.html 前 言 JRedu 随着HTML5的不断发展,移动开发成为主流趋势!越来越多的公司开始选择使用H ...
- 原生开发、H5开发、混合移动开发的优缺点
一.原生开发(Native App开发) 原生开发,是在Android.IOS等移动平台上利用官方提供的开发语言.开发类库.开发工具进行App开发.比如Android是利用Java.Eclipse.A ...
- 关于APP,原生和H5开发技术的争论
App的开发技术,目前流行的两种方式,原生和Html5.原生分了安卓平台和ios平台(还有小众的黑莓.死去的塞班就不说了),H5就是Html5. 目前争论不休的问题,在早先前争论CS,BS架构的软件系 ...
- H5外包团队 H5开发微信APP的优势有哪些
H5外包团队 H5开发微信APP的优势有哪些
- 用H5开发微信还是开发APP?
用H5开发微信还是开发APP? 随着技术的飞速发展,HTML第五版技术标准的更新,在移动端,由于其相对较低的开发成本及强大的跨平台运行能力,越来越多的信息型产品也开始选择这样轻量级的H5页面进行快速迭 ...
- 关于APP,原生和H5开发技术的争论 APP开发技术选型判断依据
关于APP,原生和H5开发技术的争论 App的开发技术,目前流行的两种方式,原生和Html5.原生分了安卓平台和ios平台(还有小众的黑莓.死去的塞班就不说了),H5就是Html5. 目前争论不休的问 ...
随机推荐
- 关于mysql的符合主键的定义和解释
DROP TABLE IF EXISTS `v9_vote_data`;CREATE TABLE `v9_vote_data` ( `userid` mediumint(8) unsigned DE ...
- spring boot 测试插件使用及result风格实例1&打包启动
本节主要内容: 1:spring boot 小插件使用 2:构建第一个简单的result风格的实例并访问 3:将项目打成jar包后启动并访问. 一:添加boot devtools插件: 执行完成后,查 ...
- 系统学习javaweb重点难点1--如何区分<input/>框里的三种常用属性:type属性 name属性 和 value属性
感想:这是我系统学习javaweb的时候感觉这个是一个初学者十分容易搞混的点 学习笔记: 首先,是type属性. 表单输入项标签之一,用户可以在该标签上通过填写和选择进行数据输入. type属性设置该 ...
- 深入JVM内核--常用JVM配置参数
Trace跟踪参数 -verbose:gc -XX:+printGC 可以打印GC的简要信息 [GC 4790K->374K(15872K), 0.0001606 secs] [GC 4790K ...
- Serializable 接口(序列化)
目录 Serializable 接口(序列化) 前言 用途 如何实现 异常 serialVersionUID transient关键字 Serializable 接口(序列化) 前言 查看API文档时 ...
- php--小数点问题
1.用round去小数点后两位时,有时候会出现很长的小数解决方法 sprintf("%.2f",round($total_fee,2)); 使用sprintf再截取一遍.出现变态小 ...
- 测试一个数字是否等于 NaN
ES6提供了一个新的 Number.isNaN() 函数,这是一个不同的函数,并且比老的全局 isNaN() 函数更可靠.
- python 通过socket实现ssh功能
功能:实现从客户端向服务端发送cmd指令,服务端将结果返回给客户端的功能. #coding:utf-8 '''服务端''' import socket,os server=socket.socket( ...
- linux安装fasttext报错,升级gcc后成功解决
首先说一下存在问题: 本人打算在linux安装一个fasttext用来训练词向量,本来是想要从gensim来调用fasttext的,但是加载大的本地txt一直不对,没办法了只好在linux安装一个fa ...
- Android--MediaPlayer(实现列表选歌,上一首,下一首,清空播放列表,搜索本地音乐文件)
Android--MediaPlayer(实现列表选歌,上一首,下一首,清空播放列表,搜索本地音乐文件) 下载链接:http://download.csdn.net/detail/zlqqhs/507 ...