wepy-開發總結(功能點)

開發小程序中,遇到的wepy的幾點坑,記錄一下;前端

更詳細的項目總結記錄請見個人我的博客:https://fanghongliang.github.io/git

1.定時器:github

  在頁面中有須要用到倒計時或者其餘定時器任務時,新建的定時器在卸載頁面時必定要清除掉,有時候頁面可能不止一個定時器需求,在卸載頁面(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,阻止事件點擊向上傳播,由於每一層都添加有點擊事件,互不干擾、app

   解決: 添加函數 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)
        },

至此,圖片上傳解決

相關文章
相關標籤/搜索