内容简介:最近接到上头的指示,要做一个体育类的小程序,并且要在元旦之前上线一版,看了下时间,距离元旦只有一个多月,而且除去测试的时间和双休,最多只有三个星期,时间相当的紧迫,而且需求文档都更新到1.3了,这也就意味着安卓和ios的版本迭代已经到了1.3了,而我们小程序要在三个星期内开发完1.0-1.3版本的功能,所以我们的时间相当的紧迫,看了下需求文档和原型图,我整个人大吃一惊,有100多个页面,我顿时懵逼了,产品经理更我说;你们只需做三个模块,最后一个模块不用做,我看了一下最后一个模块,有10几个页面,除去10几个
最近接到上头的指示,要做一个体育类的小程序,并且要在元旦之前上线一版,看了下时间,距离元旦只有一个多月,而且除去测试的时间和双休,最多只有三个星期,时间相当的紧迫,而且需求文档都更新到1.3了,这也就意味着安卓和ios的版本迭代已经到了1.3了,而我们小程序要在三个星期内开发完1.0-1.3版本的功能,所以我们的时间相当的紧迫,看了下需求文档和原型图,我整个人大吃一惊,有100多个页面,我顿时懵逼了,产品经理更我说;你们只需做三个模块,最后一个模块不用做,我看了一下最后一个模块,有10几个页面,除去10几个页面还有90多个呀,页面还好,最难的是需求文档的业务逻辑呀,而且这个项目的难度比中小型电商项目类的要难的多,交互相当的频繁和复杂,怎么办呢,一句话,凉拌,毕竟这是boss要求做的项目,只好硬着头皮往下做,不得不从。
技术选型
因小程序页面多,切交互频繁,如果用原生开发的话,时间来不急,而且页面的交互很多,这样原生小程序就显得那么的吃力了,最终我将技术选型放在了,wepy和mpvue这两个框架上,wepy框架是微信官方维护的,兼容性和扩展性很好,mpvue是美团旗下的,我最终选择了mpvue,原因是mpvue的语法跟Vue的语法是一样的,而且我们的前端同学都会Vue,所以选择mpvue是最好的选择,于是看了一下mpvue的文档和注意点,最终搭建了小程序的项目结构,将任务安排了下去,于是开启了加班的苦日子....
-
技术点1-小程序,安卓,iOS三端数据信息同步,免登陆
因项目中的登录方式含有微信登录,所以三端协商,如果用户是微信登录的话,三端统一取, unionid
这个字段,这时肯定有同学要问;为什么不取 openid
,如果做过小程序的人一定知道openid是唯一的标识,微信小程序有一个,那么在安卓,iOS他们也都有自已的openid标识,所以这样是不能达到三端数据信息同步,免登陆的效果的,微信官方介绍了6种获取 unionid
的方法,我们项目最终采用了解密获取的方法,官方文档。
import {AchieveOpenid} from '@/http/api.js'; let that=this; wx.login({ async success(resCode){ const cache=await AchieveOpenid({ //openid,内部服务器=》腾讯获取到了openid code:resCode.code }); that.openid=cache.result.unionid; wx.setStorageSync('openId',that.openid); } }) 复制代码
注意:这个方法是官方中的wx.login+code2Session方法,也确实可以获取unionid,但是天有不测风云呀,测试组的人员测出了unionid不存在的情况,而且还有几个账号也出现了这种问题,那么我们就开始找原因,最终我们发现,如果用户没有关注过任何的公众号,微信是不会给他返回unionid的,我们找到原因之后,马上换了另外一种方法,那就是解码的方式,也是我们最终的方法。
<button class='openpage-authorize' open-type="getUserInfo" lang="zh_CN" @getuserinfo="onGotUserInfo"> </button> 复制代码
//注意我这里只列举解码的代码,有些代码省略了,请熟知。 import WXBizDataCrypt from "@/utils/cryptojs/RdWXBizDataCrypt.js" //引用解码 methods:{ deCode(encryptedData,iv,sessionKey){ let wxObj=null,data=null; wxObj= new WXBizDataCrypt('wx3ea59bf3ff3a9bb8', sessionKey); data= wxObj.decryptData(encryptedData,iv); this.openid=data.unionId; wx.setStorageSync('openId',data.unionId); }, onGotUserInfo(e) { //通过按钮触发getuserinfo if(e.mp.detail.userInfo){ this.deCode(e.mp.detail.encryptedData,e.mp.detail.iv,this.sessionKey); }else{ toast('请再次授权'); } }, } 复制代码
最终我们可以通过上面的代码获取 unionId
, 解码地址下载 , 注意:解码这一步最好放在服务端解码,不要放在客户端解码,这样会造成信息泄露.....
-
技术点2-在小程序中使用canvas
wx.createCanvasContext
不懂得同学可以自已去看
微信官方文档
,代码如下
const ctx = wx.createCanvasContext('myCanvas'); ctx.setLineCap('round') var gradient1=ctx.createLinearGradient(0,0,170,0); gradient1.addColorStop("0","#FFF956"); gradient1.addColorStop("1.0","#FF6C00"); var gradient2=ctx.createLinearGradient(0,0,170,0); gradient2.addColorStop("0","#8156FE"); gradient2.addColorStop("1.0","#3AFFF1"); ctx.setLineWidth(4); ctx.beginPath(); ctx.arc(50, 50, 30,0.75*Math.PI,0.25*Math.PI,false); ctx.setStrokeStyle('#4e4f59'); ctx.stroke() ctx.beginPath(); ctx.arc(50, 50, 38,0.75*Math.PI,0.25*Math.PI,false); ctx.setStrokeStyle('#4e4f59'); ctx.stroke(); //胜 ctx.beginPath(); ctx.arc(50, 50, 30,0.75*Math.PI,(((winarc*1.5+0.75)%2)==0?2:((winarc*1.5+0.75)%2))*Math.PI,false); ctx.setStrokeStyle(gradient1) ctx.stroke() //负 ctx.beginPath(); ctx.arc(50, 50, 38,0.75*Math.PI,(((failarc*1.5+0.75)%2)==0?2:((failarc*1.5+0.75)%2))*Math.PI,false) ctx.setStrokeStyle(gradient2); ctx.stroke() ctx.setTextAlign('center'); ctx.setFontSize(16); ctx.setFillStyle('#fff'); ctx.setTextBaseline('middle'); ctx.fillText('战绩', 50, 50); ctx.draw() 复制代码
注意点:如果canva的数据是异步的话,一定要在数据加载完成之后,在让它渲染到视图层中去,如果不这样做的话,canvas会数据不同步,具体的做法可以加一个开关,如下..
<canvas canvas-id="myCanvas" class="index-header-data-circle-canvas" v-if='on'></canvas> 复制代码
data(){ return { on:false } } async xx(){ try{ const data=await xxx(); this.on=data.code==='000'?true:false; }catch (error) {} } //注意:以上代码只是模拟,仅供查考。 复制代码
-
技术点3-图片上传转化base64
图片上传微信小程序给我们提供了api, wx.chooseImage
,上传简单,关键是如何转化base64位呢,我们的舒同学用了如下的写法,看着确实没什么问题,用临时路径作为一个请求的url,把数据返回格式设置成arraybuffer,这个也确实是个办法,在微信开发 工具 里面也是ok的,但是天有不测风云呀,在真机上请求报错了,那么这种方法pass掉。
wx.chooseImage({ success:res=>{ wx.request({ url:url, responseType: 'arraybuffer', //最关键的参数,设置返回的数据格式为arraybuffer success:res=>{ let base64 = wx.arrayBufferToBase64(res.data); } }) }) 复制代码
针对上面的问题,仔细的看了下微信官方文档,最终找到了一个代码少,简单的方法, wx.getFileSystemManager()
这个api可以解决我们上面的问题,微信官方文档,代码如下
wx.chooseImage({ count: 1, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success:(res)=>{ wx.getFileSystemManager().readFile({ filePath:res.tempFilePaths[0], //选择图片返回的相对路径 encoding: 'base64', success: res => { console.log(res.data) } }) } }) 复制代码
其实除了, wx.getFileSystemManager()
可以解决我们的问题外,还有一种方法,那就是更html5一样的处理方法,通过canvas来画,然后在用canvas的api来转base64, 注意:如果通过canvas来转base64的话,有个bug,那就是在iOS手机上图片会出现旋转90度的问题
小程序可以借鉴 这个同学的方法来解决 ,如果是html5的话可以通过 exif.js 这个库来解决问题。
-
技术点4-对picker的封装
小程序中有个picker组件,他支持5中类型,虽然有5中类型但是每个项目的不同,所以对picker的用途就不同,因此我们将对picker进行封装,来达到满足我们项目的需求,我们封装省市,时间日期等组件,我这里就只介绍 省市
组件的封装,其他的组件封装原理同省市组件原理一样的,我这里就不多说了,代码如下。
<picker class="pickes" mode="multiSelector" @change="PickerChange" @columnchange="PickerColumnChange" :range="allList" range-key='provinceName' :value='multiIndex' v-if='show'> <div class="slot"></div> </picker> 复制代码
/** * @describe 省市选择器 * @rerurn 省,市,省id,市id */ import {allCity} from "@/http/api.js"; export default { data() { return { list:[], multiIndex: [0, 0], //显示化动的列数 allList:[], //存储二维数据 singleList:[], //存储一维数组 show:false, //防止数据没有加载出来 cityInfo:{}, //存储省,市,省id,市id } }, mounted(){ this.init(); }, methods:{ async init(){ try { let child=[],data=null; data=await allCity(); //获取后台返回的城市 this.singleList=data.result; child.push(data.result[0]); this.allList.push(data.result,child); this.show=true; } catch (error) {} }, PickerChange(e) { this.cityInfo.provinceId=this.singleList[e.mp.detail.value[0]].provinceId; //省id this.cityInfo.provinceName=this.singleList[e.mp.detail.value[0]].provinceName; //省名 this.cityInfo.cityId=this.singleList[e.mp.detail.value[0]].cityList[e.mp.detail.value[1]].cityId; //城市id this.cityInfo.cityName=this.singleList[e.mp.detail.value[0]].cityList[e.mp.detail.value[1]].cityName; //城市名 this.$emit('cityInfo',this.cityInfo); //将值传给父组件 }, PickerColumnChange(e) { switch (e.mp.detail.column) { case 0: this.list = []; this.singleList.forEach(item => { if (item.provinceId ==this.singleList[e.mp.detail.value].provinceId) { item.cityList.forEach(item=>{ //注意这一步最为重要,给数组添加一个和父对象一样的键值名,这样picker组件可以找的到 item.provinceName=item.cityName; }) } }); this.allList[1]=this.list; this.multiIndex[0]=e.mp.detail.value; this.multiIndex[1]=0; //注意这个表示的时选择中省切换的时候,要将省的第一个城市放在第一位 break; } }, } } 复制代码
-
技术点5-在小程序使用高德定位
因项目中要用到定位功能,而小程序中的的api并不适用项目,所以就选择了高德定位,高德小程序版文档,代码如下
//注意我这里只列举定位的代码,有些代码省略了,请熟知。 let _this = this,myAmapFun=null; myAmapFun = new amapFile.AMapWX({ key: "xxxxx" //高德的密钥 }); myAmapFun.getRegeo({ success(data){ _this.$store.dispatch('cityLocal',data[0].regeocodeData.addressComponent.city); }, fail(err) { wx.showModal({ title: '提示', content: '定位失败,请手动定位', success (res) { if (res.confirm) { path({url:'/pages/city/main'}); }else if (res.cancel) { _this.$store.dispatch('cityLocal','定位失败'); } } }) } }); 复制代码
-
技术点6-对微信小程序节点的运用
由于项目用到了城市索引选择功能,所以就采用 wx.createSelectorQuery()
这个api来实现这个功能,代码如下
<ul class="slide"> <li v-for="(item,index) in cityJson.leter" :key="index" @tap='touStart(item.letid,item.lettext)'> {{item.lettext}} </li> </ul> 复制代码
//注意我这里只列举城市索引选择的代码,有些代码省略了,请熟知。 onPageScroll(e){ this.scollTop=e.scrollTop //同步 }, methods:{ touStart(flag,text){ try { wx.createSelectorQuery().select(flag).fields({ //运用微信节点api dataset: true, size: true, rect: true, computedStyle: ['margin', 'backgroundColor'] }, (res)=> { wx.pageScrollTo({ scrollTop: this.scollTop+res.top, duration: 0 }); this.on=true; this.modalText=text; setTimeout(()=>{ this.on=false; },2000) }).exec() }catch (error) {} }, } 复制代码
当然实现上面这个功能也可以用其他的方法,如scroll-view,我这里就不多说了。
-
技术点7-返回上一层页面,刷新页面数据
我们可以通过微信中的 wx.navigateBack()
这个api就可以返回上一层页面,但是怎样返回上一层页面并且刷新呢,其实可以通过onShow这个生命周期函数来刷新页面,如果那个页面含有参数的话,最好代码这么写
onShow(){ //之所以用try,是因为mpvue官方说,如果要获取地址参数的话,最好在mounted周期里面获取,我们用try可以避免代码终止和报错 try { let id=this.$root.$mp.query.Id; this.init(id); }catch (error) {} } 复制代码
结语
由于时间的原因,我暂时先介绍这几个在小程序中常见的问题和功能,后面我会陆续介绍,如下技术栈
- vue的三种ssr方法,以及在项目中的使用
- react+redux在项目中的使用
- 打造自已的webpack,gulp开发环境
- koa框架的介绍和使用
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
高性能JavaScript
【美】Nicholas C. Zakas(尼古拉斯.泽卡斯) / 丁琛 / 电子工业出版社 / 2015-8-1 / 65
如果你使用 JavaScript 构建交互丰富的 Web 应用,那么 JavaScript 代码可能是造成你的Web应用速度变慢的主要原因。《高性能JavaScript》揭示的技术和策略能帮助你在开发过程中消除性能瓶颈。你将会了解如何提升各方面的性能,包括代码的加载、运行、DOM 交互、页面生存周期等。雅虎的前端工程师 Nicholas C. Zakas 和其他五位 JavaScript 专家介绍......一起来看看 《高性能JavaScript》 这本书的介绍吧!