不知不觉又两个月过去了,再总结一下近期的小程序开发情况
这几个月在QQ上也尝试了好几个类型的小程序,包括影评社区类的,匿名聊天类的,做到最后,还是都没有已经不怎么维护的测试类数据好看。按理说那个影评类的,有电影更新,有发帖互动,应该不差,可能QQ的用户群体还是对影评这个东西不怎么感兴趣吧,或者说使用QQ小程序的用户和喜欢影评的用户交集太小了。
WebSocket
在匿名聊天那个小程序中,使用到了WS,主要有私聊页面中当WS收到推送时,请求新的聊天数据;在首页的时候如果收到新消息的推送,展示新消息提示。
由于考虑到很多页面都会用到,所以在app.js中声明ws对象,在onLaunch事件中进行初始化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| App({ ... qqsocket: null, onLaunch(option){ let ... qqsocket = self.qqsocket; if(!qqsocket){ self.initSocket(); qqsocket = self.qqsocket; } ... }, ... });
|
在初始化方法中,通过一个对象记录各个页面的回调事件,在onMessage中依次执行。同时,还需要有一个心跳来一直维持这个WS链接
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
| App({ ... socketOnMsgCb: {}, initSocket(){ let global = this, qqsocket = qq.connectSocket({ url: `wss://${APPCONFIG.WSHOST}/api/ws` }); qqsocket.onMessage((e)=>{ let res = JSON.parse(e.data); if(res.error == ERROR.TOKEN_ERROR){ global.doLogin(msgCb); }else{ msgCb(); } function msgCb(){ for(let i in global.socketOnMsgCb){ (global.socketOnMsgCb[i])(res); } } }); qqsocket.onClose((e)=>{ if(!!global.qqsocketTimer){ clearInterval(global.qqsocketTimer); } setTimeout(global.initSocket, 3000); }); global.qqsocketTimer = setInterval(global.qqSocketPing, 5000); global.qqsocket = qqsocket; }, qqSocketPing(){ let self = this; self.qqSocketSend({ msg_type: 1, token: Util.getTheToken() }); }, qqSocketSend(objs){ let self = this, qqsocket = self.qqsocket; qqsocket.send({ data: JSON.stringify(objs) }); }, ... });
|
之后,在页面中,读取并修改app的socketOnMsgCb对象即可,此外还需要判断一下当前页面。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| Page({ ... onLoad(){ let ... msgcb = app.socketOnMsgCb; msgcb.messageGetting = (res) => { if(res.error == ERROR.AJAX_SUCCESS && res.msg_type == 2 && app.isCurrentPage("pages/message/detail")){ console.log(res); self.refrushMsgNew(); } }; }, ... });
|
登录异常
在开发过程中,发现有极个别情况,qq.login方法返回的code是一个空字符串,虽然不知道为什么但还是给登录方法加入了一个重新登录的功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| App({ ... tokenCbs: [], isGetTokening: false, doLogin(callback){ let self = this; if(callback){ self.tokenCbs.push(callback); } if(self.isGetTokening){ return } self.isGetTokening = true; qq.login({ success(res){ if(res.code === ""){ reLogin(); }else{ //ajax login //if error reLogin } } }); function reLogin(){ self.isGetTokening = false; self.globalData.reLoginTimes++; if(self.globalData.reLoginTimes >= 5){ self.exitApp(); }else{ setTimeout(self.doLogin, 1000); } } }, ... });
|
分享其他页面之后回到首页
这个需求是当用户分享非首页的页面时,其他用户点击进入的是分享的那个页面,这时会出现一种情况,就是他可能无法返回到首页了,导致很多功能会无法使用,有一种解决办法是,使用自定义的顶部菜单,这样可以在顶部添加回到首页的按钮,但这种做法也会导致整个项目要考虑的兼容性问题非常多。另一种做法是,分享出去的页面都是首页,只不过会在地址栏中带上分享页面,首页接收到之后,跳转到那个页面,这样用户点击返回时就会跳到首页了。
首先,修改app.js中的获取分享信息方法shareDetail,将当前页面的地址添加到地址栏参数之中,添加之前要转义一下。还要记得把当前页面的option也都加上,不然可能导致页面错误
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| App({ ... shareDetail(needCurrent = false){ let global = this, pages = getCurrentPages(), currentPage = pages[pages.length - 1], tmp = { title: "share title", path: "/pages/index/index" }; if(needCurrent){ let path = `/${currentPage.route}?${makeUrlParams(currentPage.options)}`; path = encodeURIComponent(path); tmp.path += `?path=${path}` } //分享用户id //tmp.path += `${needCurrent ? '&': '?'}fromuid=${Util.getTheUserID()}`; return JSON.parse(JSON.stringify(tmp));
function makeUrlParams(datas){ let tmp = []; for(let i in datas){ tmp.push(`${i}=${datas[i]}`); } return tmp.join("&"); } }, ... });
|
之后在首页的onLoad事件中,针对参数path进行判断并跳转,最好再添加一个遮照层,以避免未跳转前的页面显示问题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| Page({ ... onLoad(option){ let path = option.path || ""; if(!!path && path != ""){ path = decodeURIComponent(path); Util.showLoading(); setTimeout(()=>{ qq.navigateTo({ url: path }); setTimeout(()=>{ Util.hideLoading(); self.setData({ jumpmask: false }); }, 800); }, 250); }else{ self.setData({ jumpmask: false }); } }, ... });
|