频道栏目
首页 > 资讯 > 微信小程序 > 正文

mpvue开发大型体育项目及总结分享

19-01-16        来源:[db:作者]  
收藏   我要投稿

最近接到上头的指示,要做一个体育类的小程序,并且要在元旦之前上线一版,看了下时间,距离元旦只有一个多月,而且除去测试的时间和双休,最多只有三个星期,时间相当的紧迫,而且需求文档都更新到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的,我们找到原因之后,马上换了另外一种方法,那就是解码的方式,也是我们最终的方法。

复制代码

//注意我这里只列举解码的代码,有些代码省略了,请熟知。

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

 

 

 

 

我们可以看到上面两个项目中的案例图片,他们是用canvas画的,第一个是采用微信官方的api,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会数据不同步,具体的做法可以加一个开关,如下..

复制代码

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进行封装,来达到满足我们项目的需求,我们封装省市,时间日期等组件,我这里就只介绍省市组件的封装,其他的组件封装原理同省市组件原理一样的,我这里就不多说了,代码如下。

复制代码

/**

* @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来实现这个功能,代码如下

{{item.lettext}}

复制代码

//注意我这里只列举城市索引选择的代码,有些代码省略了,请熟知。

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框架的介绍和使用

相关TAG标签
上一篇:小程序开发采的几个坑分享
下一篇:小程序仿淘宝五级地址选择教程
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站