wepy-开发总结(功能点)
开发小程序中,遇到的wepy的几点坑,记录一下;
更详细的项目总结记录请见我的个人博客:https://fanghongliang.github.io/
1.定时器:
在页面中有需要用到倒计时或者其他定时器任务时,新建的定时器在卸载页面时一定要清除掉,有时候页面可能不止一个定时器需求,在卸载页面(onUnload钩子函数)的时候一定要清除掉当前不用的定时器
定时器用来做倒计时效果也不错,初始时间后台获取,前端处理,后台直接在数据库查询拿到的标准时间(数据库原始时间,T分割),前端需要正则处理一下这个时间:
let overTimeStr = data.over_time.split('T')
let time1 = overTimeStr[0].replace(/-/g,",")
let time2 = overTimeStr[1].replace(/:/g,',')
let overTime = time1+ ',' + time2
let overTimeArr = overTime.split(',')
that.countDownCtrl( overTimeArr, 0 );
最终把时间分割为[年,月, 日, 时, 分, 秒]的数组,(如果后端已经把时间处理过了那就更好了),然后把该数组传递给倒计时函数:
countDownCtrl( time, group ) {
let deadline = new Date()//免费截止时间,月的下从0开始
deadline.setFullYear(time[0], time[1]-1, time[2])
deadline.setHours(time[3], time[4], time[5])
let curTimeJudge = new Date().getTime()
let timeJudge = deadline.getTime()-curTimeJudge
let remainTimeJudge = parseInt(timeJudge/1000)
if( remainTimeJudge < 0) {
log('倒计时已经过期')
return;
}
this.interva1 = setInterval(() => {
let curTime = new Date().getTime() let time = deadline.getTime()-curTime //剩余毫秒数
let remainTime = parseInt(time/1000) //总的剩余时间,以秒计 let day = parseInt( remainTime/(24*3600) )//剩余天
let hour = parseInt( (remainTime-day*24*3600)/3600 )//剩余小时
let minute = parseInt((remainTime-day*24*3600-hour*3600)/60)//剩余分钟
let sec = parseInt(remainTime%60)//剩余秒
hour = hour < 10 ? '0' + hour : hour;
minute = minute < 10 ? '0' + minute : minute
sec = sec < 10 ? '0' + sec : sec
let countDownText = hour+ ":" +minute+ ":" +sec
if( group === 0) { //个人业务逻辑,因为一个页面有两个倒计时需求,代码复用区分
this.countDown = countDownText;
} else if( group === 1 ) {
this.countDownGroup = countDownText
}
this.$apply()
}, 1000 );
}
至此,倒计时效果处理完毕,PS:终止时间一定要大于currentDate,否则显示会出现异常(包括但不限于倒计时闪烁、乱码等)
最后,退出该页面去其他页面时,一定要在页码卸载钩子中清除倒计时!!!
onUnload() {
clearInterval(this.interva1);
}
2.三层组件,阻止点击事件传播:
三层组件嵌套,第三层的点击事件不能传到第一层去,适用于遮罩层+picker,阻止事件点击向上传播,因为每一层都添加有点击事件,互不干扰、
解决: 添加函数 catchtap="funcName" 即可,funcName可为空函数,也可以直接不写
3.组件传值:
组件传值和Vue有点细微区别,Vue强调父组件的数组和对象不要直接传到子组件使用,应为子组件可能会修改这个data,如图:
但是,wepy中,有时候确实需要把一个对象传递到子组件使用,单个传递对象属性过于繁琐,而且!!!如果单个传递对象的属性到子组件,如果该属性是一个数组,则子组件永远会接收到 undefined 。此时最好用整个对象传值替代单个对象属性逐个传值的方法,
且一定要在传值时加入 .sync 修饰符,双向传值绑定。确保从接口拿到的数据也能传递到子组件,而非 undefined
:circleMembersList.sync="circleMembersList"
4.token判断
在与后台交互的时候,token必不可少。尤其是在小程序分享出去的链接,由其他用户点开分享链接进入小程序内部,此时更是要判断token,token的判断一般选在 onShow()钩子执行而不在 onLoad()钩子内执行。若不存在token,则应该执行登录去拿取token
5.formID
微信提供了服务通知,即在你支付、快递等行为时,微信会直接给你发一个服务通知来提醒,每次提醒都会消耗该用户存储的formID,formID为消耗品,用一个少一个,只有通过用户的表单提交行为才可以拿到formID,
<form @submit="submitForm" report-submit="true">
<button form-type="submit" class="editCard" @tap = "goModifiPage('editFormTab')">修改</button>
</form>
submitForm(e) {
this.postFormId( e.detail.formId )
}
6.微信支付
准备: crypto-js.js md5.js
微信支付流程为: 前端点击支付按钮 ==》 准备加密数据 ==》 调用后端接口,传入需要的加密数据 ==》 后端验证加密数据,再返回加密数据 ==》 前端拿到后端加密数据(时间戳、内容、签名),对时间戳和内容进行本地签名,再判断本地签名和后端签名是否
一致,若不一致,直接返回,退出支付,支付失败!若一致,对刚刚后台返回的content(内容)进行解析,拿到所需订单数据,前端调起微信支付借口,参数传入刚刚解析数据 ===》 得到支付结果 success or fail !结束
Sign函数:
/**
* 签名
*/
function sign(timestamp, content) {
var raw = timestamp + salt + content
var hash = CryptoJS.SHA256(raw).toString()
return CryptoJS.MD5(hash).toString()
}
前端点击支付按钮:
// 单独支付接口
alonePay(arg) {
const that = this;
if( that.buttonClicked === false ) return;
that.buttonClicked = false;
let mode = 1;
let appId = this.$parent.globalData.appId;
let content;
let sign;
const timeStamp = new Date().Format("yyyy-MM-dd hh:mm:ss").toString();
let code = wepy.getStorageSync('code');
wepy.login().then((res) => {
if(res.code) {
let code = res.code;
log('code', code)
wepy.setStorage({
key: "code",
data: code
})
}
}).then( res => {
content = `mode=${mode}&app_id=${appId}`
sign = Sign.sign(timeStamp,content);
}).then(res => {
that.goCirclePay( that.circle_id, timeStamp, sign, content, mode )
})
},
支付函数:
// 支付
goCirclePay( circle_id, timestamp, sign, content, mode) {
const that = this;
circleApi.goCirclePay({
data: {
circle_id,
timestamp,
sign,
content
},
getToken: true
}).then( res => {
log('支付res:', res) let data = res.data
const SignServer = data.sign
const timeStampServer = data.timestamp
let contentServer = data.content
const SignLocal = Sign.sign(timeStampServer,contentServer); if( mode === 0 && data.status === "success") {
that.nav('/pages/circleDetail?circle_id=' + that.circle_id)
return;
} if( SignLocal !== SignServer ) {
log('签名不一致!')
wx.showToast({
title: "您已经支付过了",
duration: 1500,
image: "../images/common/icon_wxchat.png",
})
return
}
let contentArr = contentServer.split('&')
const timeStamp = contentArr[0].split('=')[1];
const nonceStr = contentArr[1].split('=')[1];
let index = contentArr[2].indexOf("=");
const package1 = contentArr[2].slice(index+1)
const signType = contentArr[3].split('=')[1];
const paySign = contentArr[4].split('=')[1];
wepy.requestPayment({
timeStamp,
nonceStr,
package: package1,
signType,
paySign
}).then(res => {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, 1000)
})
}).then(res => {
that.buttonClicked = true;
let groupFormIdGet;
circleApi.getGroupFormId({ ////获取getGroupFormId
data: {
circle_id: that.circle_id
},
getToken: true
}).then( res => {
let data = res.data
that.group_form_id = data.group_form_id
groupFormIdGet = data.group_form_id if( mode === 1) {
that.nav(`/pages/paySuccess?circle_id=${that.circle_id}&shareLink=${that.shareLink}`)
} else if( mode === 2) {
that.nav(`/pages/paySuccess?circle_id=${that.circle_id}&group_form_id=${groupFormIdGet}`)
}
that.$apply()
})
}).catch(res => {
log('支付失败', res)
that.buttonClicked = true;
})
})
}
至此,支付就已经完成!
7.图片上传(采用七牛云)
图片上传服务器采用七牛云服务,在APP内小程序触发的时候,请求七牛云拿到token存为全局变量。
图片需要上传的地方,直接放代码:
页面结构:
<!-- 上传生活照 -->
<view class="baseInfoTip" style="border: 0">上传生活照
<view class="imgUploadText">(最多9张)</view>
<view class="leftOriginLine"></view>
</view>
<view class="uploadImgBox">
<repeat for="{{images}}" index="index" item="item" key="index">
<view class="itemBox">
<image class="imgItem" src="{{item}}" mode="aspectFill"></image>
<image class="imgItemCancel" id="{{index}}" src="../images/common/icon_cardImg_cancel.png" @tap.stop="cancelUploadImg"></image>
</view>
</repeat>
<view class="itemBox" @tap="addImg" wx:if="{{!addImgCtrl}}">
<image class="imgItem" src="../images/common/icon_addImg.png"></image>
</view>
</view>
base.oploadImg()函数:
// 上传图片
const uploadImg = (imageURL, uptokenURL) => {
return new Promise((resolve, reject) => {
qiniuyun.upload(imageURL, (res) => {
resolve(res);
}, (error) => {
reject(error);
}, {
region: 'ECN',
domain: '填入域名',
uptoken: uptokenURL
});
});
}
上传图片函数:
// 从相册选择照片上传
addImg(){
const that = this;
if( that.buttonClicked === false ) return;
that.buttonClicked = false;
wepy.chooseImage({
count:9 - that.images.length,
sizeType: 'compressed',
}).then(async(res1) => {
that.buttonClicked = true;
that.toast('上传图片中...','loading');
let filePath = res1.tempFilePaths;
for(let i = 0;i < filePath.length;i++){
let imgSrc= res1.tempFilePaths[i];
let imgType = imgSrc.substring(imgSrc.length-3);
let imgSize = res1.tempFiles[i].size;
if(imgSize > 2000000 || imgType === 'gif'){
that.toast('该图片格式错误!请重新选择一张', 'none', 3000);
continue
}
let res = await base.uploadImg(filePath[i], that.$parent.globalData.qiniuToken);
that.images.push(res.imageURL);
log('image长度:', that.images.length)
log('image:', that.images)
if( that.images.length >= 9) {
that.addImgCtrl = true
}
if(that.images.length > 9){
that.images = that.images.slice(0,9)
}
if(that.images.length >0 && that.config.fImages){
that.config.progress = that.config.progress + parseFloat(that.config.getConfigs.lifepicweight*100);
that.config.fImages = false
}
that.$apply();
// 上传用户头像列表
that.userInfo.photos = that.images
if(i === filePath.length -1){
wepy.hideToast();
}
}
}).catch((res) => {
if(res.errMsg === "chooseImage:fail:system permission denied"){
that.toast('请打开微信调用摄像头的权限', 'none', 3500)
}
})
},
// 取消图片上传
cancelUploadImg(e) {
if( this.images.length < 10 ) {
this.addImgCtrl = false
}
let index = e.target.id
this.images.splice(index, 1)
},
至此,图片上传解决
wepy-开发总结(功能点)的更多相关文章
- python_way day18 html-day4, Django路由,(正则匹配页码,包含自开发分页功能), 模板, Model(jDango-ORM) : SQLite,数据库时间字段插入的方法
python_way day18 html-day4 1.Django-路由系统 - 自开发分页功能 2.模板语言:之母板的使用 3.SQLite:model(jDango-ORM) 数据库时间字 ...
- iOS项目开发常用功能静态库
YHDeveloperTools iOS项目开发常用功能静态库 查看源码 功能方法: 1.字符检查 [NSString checkStringWithType:Email andTargetStrin ...
- 微信小程序wepy开发循环wx:for需要注意
微信小程序wepy开发循环wx:for需要注意 item index值必须在wx:for之后使用 <view wx:for="{{tablist}}" class=" ...
- wepy开发小程序eslint报错error 'getApp' is not defined no-undef
wepy开发小程序使用getApp().globalData保存全局数据很方便,但是会在控制台看到很多报错:“error 'getApp' is not defined no-undef”,这是esl ...
- Django框架之cookie和session及开发登录功能
1.cookie是什么? Web应用程序是使用HTTP协议传输数据的.HTTP协议是无状态的协议.一旦数据交换完毕,客户端与服务器端的连接就会关闭,再次交换数据需要建立新的连接.这就意味着服务器无法从 ...
- NFC模组,开发NFC功能 仅仅要几条指令的事情
特点:实现NFC透明传输.内置NFC协议栈,支持UART串口直接读写,用于门禁能够同一时候兼容手机和卡片开门,还能实现动态密钥,读到的NFC数据自己主动串口输出,会串口就能开发NFC,不须要研究LLC ...
- 阿里云短信服务发送短信验证码(JAVA开发此功能)
开发此功能需注册阿里云账号,并开通短信服务(免费开通) 充值后,不会影响业务的正常使用!(因为发送验证类短信:1-10万范围的短信是0.045元/条).开发测试使用,充2块钱测试足够了 可参考阿里云官 ...
- 使用wepy开发微信小程序商城第三篇:购物车(布局篇)
使用wepy开发微信小程序商城 第三篇:购物车(布局篇) 前两篇如下: 使用wepy开发微信小程序商城第一篇:项目初始化 使用wepy开发微信小程序商城第二篇:路由配置和页面结构 基于上两篇内容,开始 ...
- 使用wepy开发微信小程序商城第二篇:路由配置和页面结构
使用wepy开发微信小程序商城 第二篇:路由配置和页面结构 前言: 最近公司在做一个微信小程序的项目,用的是类似于vue的wepy框架.我也借此机会学习和实践一下. 小程序官方文档:https://d ...
- 使用wepy开发微信小程序商城第一篇:项目初始化
使用wepy开发微信小程序商城 第一篇:项目初始化 前言: wepy小程序项目初始化的操作,官方文档看了好几遍,感觉写得不是很清楚. 这篇写得挺好的:小程序开发之wepy 1.初始化项目 (1)全局安 ...
随机推荐
- Mac OS 10安装CocoaPods流程
一.简介 什么是CocoaPods CocoaPods是OS X和iOS下的一个第三类库管理工具,通过CocoaPods工具我们可以为项目添加被称为“Pods”的依赖库(这些类库必须是CocoaPod ...
- 软件-客户端管理工具-SourceTree:百科
ylbtech-软件-客户端管理工具-SourceTree:百科 SourceTree 是 Windows 和Mac OS X 下免费的 Git 和 Hg 客户端管理工具,同时也是Mn版本控制系统工具 ...
- VS调试异常代码 HRESULT:0x80070057 (E_INVALIDARG)解决方法
我目前在做的一个系统是VS2010写的的B/S架构程序, 主要技术是:C#.SQLSERVER2008.NHibernate,Python,Nhibernate 的*.hbn.xml是映射数据库的表结 ...
- spring hibernate 事务整合 使用测试类 事务不自动提交的问题!!!
使用JUnit 测试hibernate 事务管理的时候应注意 ,测试类完成是默认回滚的. 所以只能查询数据库却不能增删改数据库. 应该在测试类上面加上注解 @Rollback(false) 表似默认 ...
- Debian系统中当安装deb软件时出现:deb cdrom:[Debian GNU/Linux 9.3.0 _Stretch_ - Official amd64 DVD Binary-1 20171209-12:11]/ stretch contrib main
vi /etc/apt/sources.list // 注释掉下面这句话# deb cdrom:[Debian GNU/Linux 9.3.0 _Stretch_ - Official amd64 D ...
- kafka学习(二)
创建kafka生产者 要往kafka写入消息,首先要创建一个生产者对象,并设置一些熟悉.kafka生产者有3个必选的属性. 1.bootstrap.servers 该属性指定broker的地址清单 ...
- java版微信支付/查询/撤销
最近公司接入微信刷卡支付,网上根本没见到很直接的教程(可能眼拙),一直摸滚打爬,加班加点才走通,忍不了必须写一写 微信 刷卡支付/查询/撤销... 必须要有公众号然后去申请,申请自己去看文档,这里主要 ...
- [转帖]挖洞经验 | 获取Facebook Marketplace卖家精确地理位置信息
挖洞经验 | 获取Facebook Marketplace卖家精确地理位置信息 https://www.freebuf.com/vuls/202820.html 知识就是力量 5000刀的一个漏洞. ...
- CentOS 8 下 nginx 服务器安装及配置笔记
参考文档 nginx官方文档 安装 在CentOS下,nginx官方提供了安装包可以安装 首先先安装前置软件 sudo yum install yum-utils 然后将nginx官方源加入到yum源 ...
- P2010回文日期
这道题是2016年普及组的题,难度等级为普及-. 这道题仍然是个模拟题.有两种策略:1.枚举回文,看日期是否存在2.枚举日期,看是否是回文.显然,前者要快很多,并且准确.本蒟蒻第一次便使用了后者,bu ...