zoukankan      html  css  js  c++  java
  • 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)
            },

    至此,图片上传解决

      

  • 相关阅读:
    How to interpret complex C/C++ declarations (ZT)
    The Managed Thread Pool
    How slow is dynamic_cast?
    Type Safety
    sBRDF空间双向反射分布函数完全解析
    近日工作与生活梗概
    简单的环绕散射 Simple Wrap Diffuse From GPU GEMS1
    屈辱史
    难以忽视的细节
    物理学与计算机图形学中的HDR
  • 原文地址:https://www.cnblogs.com/fanghl/p/11248736.html
Copyright © 2011-2022 走看看