小程序项目总结
项目快做完了,做下总结:
需求:登录模块、设备列表展示模块、个人中心模块、详情模块,总共分为这四个模块内容。
一、拿到项目需求后,先创建了一下项目,然后封装了一些常用的方法,http请求和时间处理函数Date
1、封装http请求,比较简单用Promise 进行封装,把返回的数据resolve(res),然后把http.js引入到全局app.js中,利用globalData{}对象进行全局管理。
const baseUrl = 'https://xxx'
let http= (method, urlData)=>{ return new Promise((resolve,reject)=>{ wx.request({ url: baseUrl + urlData.url, data: urlData.data, method: method, header: { "Content-Type": "application/json", "Authorization": wx.getStorageSync('token') }, success: function (res) { resolve(res) }, fail: function (err) { reject(err) } }) }) } export default http
2、因为项目中需要对时间进行处理,后台返回的是时间戳这里就封装了一个时间转换处理函数,代码比较简单,同http一样引入全局。
二、想了想为了加快开发速度,就在项目中引入vant ui 框架,使用简单npm 下载下来,在开发工具中构建一下npm就ok了,使用方法官方已给出:https://vant-contrib.gitee.io/vant-weapp/#/intro
三、登录模块开发
需求:一键登录、输入账号密码登录,两种方式
1、一键登录
分析:
(1)、一键登录的账号主要来源是微信绑定的手机号码,所以我们要进行手机号码授权(拿到encryptedData和iv,后端解码获取到手机号码)
(2)、在登录时我们需要获取code登录标识(有时间限制,只能使用一次)
(3)、发送登录请求,把code、encryptedData、iv提交给后端做登录处理,返回sessionkey和token并保存
2、账号密码登录
分析:
(1)、发送请求向后端提交账号和密码,返回token并保存
(2)、这里输入账号和密码是要做双向绑定,监听输入事件把输入内容赋值给user和password
(3)、在做清空和密码隐藏显示时图标不要放在输入框内,不然会触发冒泡,键盘不会收回
(4)、注意在隐藏和显示密码这儿,一定好看清文档,是password属性的true和false来控制隐藏于显示,不是type属性
这块内容没啥难点,不放代码了!
四、首页&列表页面
1、初始化页面
分析:
(1)、在页面加载前要判断是否已登录(根据保存的token和sessionkey)
(2)、已登录下,区分是一键登录还是账号密码登录(账号密码登录无sessionkey),然后直接请求列表数据,请求根据状态码如果token过期,走刷新token的接口(刷新成功则保存刷新后的token重新进入该页面,否则提示重新登录 ==> 清空缓存 ==> 跳转到登录页)
2、页面布局
九宫格布局----父盒子
wx.previewImage({
urls: urlList //urlList是数组
})
2、退出登录要清空缓存
六、详情页面
需求:展示设备详情数据,设备差不多100种左右,每个设备的ui不同;重点来了,不同设备详情页面可以左右滑动到下一个页面(顺序为首页的顺序,滑动效果轮播图那样)
天哪这一个页面得写多少代码啊啊啊...,后台接口只有获取设备列表和根据设备id获取详情数据,且格式由于是转发不能修改
额,只能一点点写了,
1、直接把官方的swiper组件拿过来开撸,为了减少请求直接把首页请求的设备列表list传到的详情页并保存
2、初始化,根据传递的设备id,请求详情数据,把需要的数据绑定到list数组下对应的设备数据对象中
3、dom结构是根据不同设备ui进行了划分,共有的和私有的,通过wx-if来进行要渲染的内容
4、要区分当前详情数据第几页,这里首先把拿到的list数组过滤,得到有详情页的数据列表(有些设备无详情页),然后循环查找当前的设备id,循环的key+1值就是第几个设备,并且把当swiper组件的当前页页设置为key。
5、左右滑动的时候,根据滑动后触发事件,获得的索引作为list的索引,拿到下个设备的id,然后进行渲染(渲染前清除上个设备的dom)
6、这里且套了多次循环,主要还是请求到的数据格式不理想,导致了写了很多处理格式的代码
7、测试,发现bug,左右来回滑动很快的时候,停下来后页面会不停抖动,查了下是组件的bug。
解决方式:对滑动事件触发后 的触发源做判断,如果是touch则进行页面渲染,解决了抖动问题;
测试发现出现无法滑动的bug,分析是滑动后更改当前页导致
解决方式:做节流,当触发滑动事件后到渲染数据这段时间禁止页面滑动,当渲染完成才允许滑动,现在就是如何禁止页面滑动,组件没这个属性,想到通过添加一个透明层来阻止滑动执行(有更好的方法的小伙伴可以分享下)。
7、需要增加要实时更新数据和上报推送消息-------webSocket
上网找了下有很多现成的轮子,看了下很简单。
附上原文地址:https://www.cnblogs.com/nanyang520/p/11200857.html
var sotk = null; var socketOpen = false; var wsbasePath = "ws://开发者服务器 wss 接口地址/"; //开始webSocket webSocketStart(e){ sotk = wx.connectSocket({ url: wsbasePath, header: { 'content-type': 'application/x-www-form-urlencoded' }, method: "POST", success: res => { console.log('小程序连接成功:', res); }, fail: err => { console.log('出现错误啦!!' + err); wx.showToast({ title: '网络异常!', }) } }) this.webSokcketMethods(); }, //监听指令 webSokcketMethods(e){ let that = this; sotk.onOpen(res => { socketOpen = true; console.log('监听 WebSocket 连接打开事件。', res); }) sotk.onClose(onClose => { console.log('监听 WebSocket 连接关闭事件。', onClose) socketOpen = false; }) sotk.onError(onError => { console.log('监听 WebSocket 错误。错误信息', onError) socketOpen = false }) sotk.onMessage(onMessage => { var data = JSON.parse(onMessage.data); console.log('监听WebSocket接受到服务器的消息事件。服务器返回的消息',data); }) }, //发送消息 sendSocketMessage(msg) { let that = this; if (socketOpen){ console.log('通过 WebSocket 连接发送数据', JSON.stringify(msg)) sotk.send({ data: JSON.stringify(msg) }, function (res) { console.log('已发送', res) }) } }, //关闭连接 closeWebsocket(str){ if (socketOpen) { sotk.close( { code: "1000", reason: str, success: function () { console.log("成功关闭websocket连接"); } } ) } }
8、需求更改 要用MQTT
好吧,开撸
分析需要:在详情页面只刷新页面数据不做消息提示,其他页面做弹框推送提示
下载mqtt.js 地址:https://unpkg.com/mqtt@4.1.0/dist/mqtt.min.js
代码mqtt全局连接,如果没有页面都要连接一次的话会出现bug ,webSocket连接有次数限制,官方说明:https://developers.weixin.qq.com/miniprogram/dev/api/network/websocket/wx.connectSocket.html
这里因为要在登录之后连接mqtt,并且主题是动态根据用户id而改变的,所以这里封装了个Promise,并把连接后的client导出,做数据监听。
var mqtt = require('utils/mqtt.min.js'); var client = null; var connect = function(id) { return new Promise((resolve,reject)=>{ const options = { connectTimeout: 4000, // 超时时间 clientId: 'wx_' + parseInt(Math.random() * 100 + 800, 10), port:8084 } client = mqtt.connect('wxs://xxx', options) client.on('reconnect', (error) => { console.log('正在重连:', error) }) client.on('error', (error) => { console.log('连接失败:', error) }) let that = this; client.on('connect', (e) => { console.log('成功连接服务器') //订阅主题 client.subscribe(['主题1'+id, '主题2'+id], { qos: 1 }, function (err) { if (!err) { console.log("订阅成功") resolve(client) } }) }) }) }
监听:
client.on('message', function (topic, message, packet) { console.log(packet) })
注意它来了!
connect(id)只在首页调用一次,并且把返回的client存为全局使用,然后就可以在详情页面中通过全局client直接监听messgae并做响应的逻辑了。
关闭连接:在退出登录或者判断token不存在的时候执行,由于关闭后它会可能自动连接,所以最好是在判断token不存在时关闭连接
wx.closeSocket()
附官方文档:https://github.com/mqttjs/MQTT.js
结束啦!
整体就这些内容,具体的不同设备ui的问题涉及的一些知识点,以后有时间在补存或另写一章。