小程序入坑全紀錄(持續更新)

關於服務器域名的配置

小程序中wx.request請求的接口,必須要在後臺開發設置中配置對應的域名,如果api有端口,則配置域名時必須帶上端口。值得注意的是,微信一個月內只允許申請修改5次,由於後臺提供的接口端口號比較多,剛開始沒有意識到這個問題,導致後面無法配置剩餘的域名端口進而無法訪問,這是一個很蛋疼的問題,最終在和後端同事的討論下,借用已配置的域名做了一箇中轉,也就是我去訪問已配置的域名,傳要請求的api和參數及請求方式給他,他那邊去幫我做請求然後將結果返回我,目前只能這樣處理了,等後面再改回來吧,希望看到的朋友注意一下。

關於業務域名的配置

小程序不存在iframe和localtion.hred的概念,所以要想跳轉外鏈,需藉助web-view標籤,web-view所跳轉的鏈接必須在後臺進行業務域名的配置,配置時注意以下幾點:1.域名需經過備案 2.域名可校驗,也就是說必須是自己的網站或者說是自己可以控制操作的網站 3.域名中不能含有端口號 4.注意修改次數,一年只可修改50次,最多可配置20個

在這個過程當中,同樣遇到過一個很蛋疼的問題,首先我的h5頁面是公用的,既想在app裏也可在小程序裏,爲了和ios那邊交互,我的h5頁面引用了一個必須的js文件,而這個js文件裏又加載了另外一個域名,web-view打開時默認也會去加載這個域名,而這個域名呢並不是我的,我也無法控制,所以就沒法進行校驗從而不能再後臺業務域名裏進行配置,從而被微信識別爲非法域名不能正常進行訪問。最開始採用的解決方案是單獨再寫一個不引用交互js的頁面,但考慮到後期公用的頁面比較多,也不可能一個一個去重寫,也不是我想要的結果,於是就從交互js上入手,在js裏域名那塊做了判斷,判斷是否在微信裏打開,如果是則不訪問該域名,因爲小程序裏不存在和ios的交互,所以也就不存在影響的問題。

點擊事件和參數傳遞

小程序的點擊事件不同於vue的@click和原生js的onclick而是用的bindtap='alert',alert爲方法名
如果需要傳遞參數,則需要在點擊元素上進行參數的定義,如data-obj='123',obj爲自定義 123爲值
方法裏面接受參數:
alert(e){
  let obj = e.currentTarget.dataset.obj;    // view接參格式
  let obj = e.target.dataset.obj;    // text接參格式
}

路由跳轉及傳參

最常用的莫過於wx.navigateTo,參數傳遞採用url拼接參數的形式,如果需要傳遞對象,可將對象轉化爲json字符串形式
wx.navigateTo({
  url: '../home/home?id=123'
})
被跳轉頁面接參,可在監聽頁面加載生命週期中進行
onLoad: function (options) {
  this.setData({
    id: options.id,
  })
},
需要注意的是,從普通頁面跳轉到tabBar頁面,需要用wx.switchTab
但目前switchTab不支持url傳參,如果想要傳遞參數,可考慮使用定義全局變量的方式

background-image不顯示

小程序用background-image設置背景圖片,在開發工具裏面看可以顯示,但在真機上無法顯示,查閱後才知道,背景圖片目前不支持加載本地資源,需加載網絡資源,可以考慮將圖片放到遠程服務器上面去。

onLoad和onShow的區別

onLoad 監聽頁面加載,頁面第一次加載是會觸發,可以把一些不需要實時更新的數據放入。
onShow 監聽頁面顯示,頁面加載就觸發,建議少放置操作減少請求。
之所以會關注這個問題 是在做登錄那塊的功能是 需要在storage裏面存儲一個參數 完了在首頁裏獲取 但發現在首頁裏默認習慣性在onLoad裏面去拿並不能及時獲取到 需要刷新重新加載之後纔可以 排除了異步加載的可能性之後 最終在onShow裏去獲取發現確實可以及時拿到 因爲onShow監聽的是頁面顯示 只要加載就會觸發

如何實現列表上拉加載和下拉刷新

最開始用的是小程序的視圖容器scroll-view去做,給定容器高度(如果是滿屏的話可以用wx.getSystemInfo獲取屏幕高度),然後用bindscrolltoupper和bindscrolltolower監聽滾動到頂部和底部,從而實現下拉刷新和上拉加載的目的。但配置和邏輯相對比較麻煩,有多個需要注意的點。

後來發現了一個更好的方法,就是page頁面本身提供的onPullDownRefresh和onReachBottom函數,直接監聽用戶是否有下拉刷新和上拉加載的動作,配置方便,邏輯判斷簡單。但缺點是,只能監聽整個頁面的動作,不能監聽頁面內的某一個容器的滾動事件,這一項不如scroll-view那樣靈活。

  // 頁面下拉 歸爲首頁 下拉刷新
  onPullDownRefresh: function () {
    // 顯示導航欄loading
    wx.showNavigationBarLoading();
    // 調用接口加載數據
    this.setData({
      pageIndex: 1,
      list: [],
      isEnd: false,
    })
    this.getList();
    // 隱藏導航欄loading
    wx.hideNavigationBarLoading();
    // 當處理完數據刷新後,wx.stopPullDownRefresh可以停止當前頁面的下拉刷新
    wx.stopPullDownRefresh();
  },
  // 頁面上拉 向上滑 類似於向下翻頁
  onReachBottom: function () {
    if (!this.data.isEnd) {
      this.setData({
        pageIndex: this.data.pageIndex + 1
      })
      this.getList()
    }
  },

需要注意的是,使用時需要在json裏配置導航欄的樣式,否則下拉加載三個點效果看不是很清楚

{
  "usingComponents": {},
  "navigationBarTitleText": "我的訂單",
  "enablePullDownRefresh": true,
  "backgroundTextStyle": "dark"
}

具體怎麼用,因需求而定;以上方式,僅供參考。

rich-text解析html時如何讓圖片自適應

html.replace(/\<img/gi, '<img style="max-width:100%;height:auto"')

全局變量的定義和使用

1.在app.js中定義全局參數userInfo

2.在對應頁面js中 使用getApp().userInfo獲取

單個頁面配置導航欄爲自定義

1.剛開始百度 都說只能在app.json裏window對象下配置全局的 可是我的需求是隻是單獨的頁面需要配置 如果全局配置的話 其他頁面的樣式都要跟着修改 太麻煩了

2.然後查看了微信官方給出的文檔 說是支持單頁面配置 但對於導航欄樣式僅限7.0.0版本以後

小程序集成微信支付(前端)

1.用wx.login方法獲取code後換取openid(後臺獲取 微信安全限制不讓前端攜帶appid和secret去請求)
2.傳入openid和商品價格數量等參數生成商戶訂單
3.用訂單號獲取支付參數
4.拿到支付參數 用wx.requestPayment喚起支付完成支付操作

獲取openid接口https://api.weixin.qq.com/sns/jscode2session?appid=APPID&secret=SECRET&js_code=JSCODE&grant_type=authorization_code
參考鏈接https://www.cnblogs.com/oneall/p/9548448.html

自定義導航欄時iPhoneX適配問題

1.app.js globalData對象中定義全局屬性navHeight:0,然後在onLaunch中賦值
    // 獲取手機系統信息
    wx.getSystemInfo({
      success: res => {
        //導航高度
        this.globalData.navHeight = res.statusBarHeight + 46;
      }, fail(err) {
        console.log(err);
      }
    })
2.在對應的頁面中獲取導航欄高度屬性值
    this.setData({
      navH: getApp().globalData.navHeight
    })
3.爲導航欄添加樣式
<view class="tab" style='height:{{navH}}px;padding-top:calc({{navH-35}}px)'></view>
<view class="container" style='padding-top:calc({{navH}}px)'></view>

小程序中如何定義倒計時

1.util.js中定義方法並拋出

function getKillTime(killTime) {
  // 計算目標與現在時間差(毫秒)
  let time1 = new Date(killTime).getTime();
  let time2 = new Date().getTime();
  if (time1 > time2){
    let mss = time1 - time2;
    // 將時間差(毫秒)格式爲:天時分秒
    let days = parseInt(mss / (1000 * 60 * 60 * 24));
    let hours = parseInt((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
    let minutes = parseInt((mss % (1000 * 60 * 60)) / (1000 * 60));
    let seconds = parseInt((mss % (1000 * 60)) / 1000);
    // 返回需要的格式
    return (hours < 10 ? '0' + hours : hours) + ":" + (minutes < 10 ? '0' + minutes : minutes) + ":" + (seconds < 10 ? '0' + seconds : seconds)
    // return days + "天" + hours + "時" + minutes + "分" + seconds + "秒"
  }else{
    return false
  }
}
module.exports = {
  getKillTime: getKillTime
}

2.在對應的頁面中引入util.js

const util = require('../../utils/util.js')
data: {
  killTime: "2019/07/25 19:59:00 GMT+0800", // 秒殺開始時間
  killTimeShow: ""    // 剩下的時間(天時分秒)
},
// 獲取秒殺時間 由於我這邊需要對時間做一些樣式處理 所以單獨拿出來時分秒
    let timer = setInterval(() => { //注意箭頭函數!!
      if (util.getKillTime(this.data.killTime)){
        let hour = util.getKillTime(this.data.killTime).substr(0, 2)
        let minute = util.getKillTime(this.data.killTime).substr(3, 2)
        let second = util.getKillTime(this.data.killTime).substr(6, 2)
        this.setData({
          // killTimeShow: util.getKillTime(this.data.killTime)
          killTimeShow: '<span class="span">' + hour + '</span>' + ':' + '<span class="span">' + minute + '</span>' + ':' + '<span class="span">' + second + '</span>',
        });
      }else{
        clearInterval(timer);
      }
    }, 1000);

點擊按鈕分享指定頁面(小程序暫不支持分享指定h5鏈接出去,網上有說用web-view做的還是分享出去的是一個小程序,只不過裏面是h5的內容)

<button plain="true" class="item" data-id="shareBtn" open-type="share">
  <image src="https://tb-images.oss-cn-shenzhen.aliyuncs.com/wxapp/wechat.png"></image>微信
</button>
/**
   * 用戶點擊右上角分享
   */
  onShareAppMessage: function (options) {
    let id = options.target.dataset.id;
    return {
      title: '好友幫砍',
      path: '/pages/bargain/help?id=' + id,
      imageUrl: '',  //用戶分享出去的自定義圖片大小爲5:4,
      success: function (res) {
        // 轉發成功
        wx.showToast({
          title: "分享成功",
          icon: 'success',
          duration: 2000
        })
      },
      fail: function (res) {
        // 分享失敗
      },
    }
  }

小程序中給對象屬性賦值;給對象新增屬性賦值

let value = 'aaa.name'; // 給對象已有屬性賦值
let value2 = `aaa.${'age'}` // 給對象新增屬性並賦值 注意引號
this.setData({
  [value]:'我是名字',
  [value2]:'我是年齡'
})

事故性問題:小程序發版本,提交了好幾次都被駁回了,而我這邊又再進行新模塊的開發,每次都要回退到之前那個版本去,來回切換了有七八次,也比較着急,可能是開發工具裏有緩存,導致最終提交的代碼部分頁面樣式錯亂,我這邊看到審覈通過了也就直接發佈正式了,市場那邊接到命令後也就直接推廣宣傳了,但線上是有問題的這就比較尷尬,這裏需要注意一下,每次提交代碼之後,儘量在體驗版裏整體走一遍測一遍,確保沒有問題,再提交審覈,即便已經測試過了。

小程序與h5的交互(頁面跳轉及傳參)

1.小程序跳h5 直接採用web-view命令 設置src屬性即可 參數傳遞可採用url拼接的方式
2.h5跳小程序
第一步 引入微信開放js文件 這裏請注意版本 我最開始引入的是1.2.0 跳轉不成功
<script src="https://res.wx.qq.com/open/js/jweixin-1.3.2.js"></script>
第二步 判斷h5打開的環境 執行對應的操作
      goDetail(id){
        var smallPro=false;
        wx.miniProgram.getEnv(function(res) {
          console.log(res.miniprogram) // 是否在微信打開
          if(res.miniprogram){
            smallPro=true;
          }else{
            smallPro=false;
          }
        });
        if(smallPro){
          wx.miniProgram.navigateTo({
            url:'../service/detail?id=' + id + '&areaId=' + 859,  // 跳轉到小程序的服務詳情頁
          });
        }else{
          this.getDevice().method.saveData('service',{  // 跳轉到app的服務詳情頁
            serviceId:id,
            areaId:859,
          });
        }
      },

小程序中在線生成分享的h5鏈接二維碼

1.剛開始想到的是引用第三方js用代碼生成 完了再github上找了幾個發現引用到的項目裏 生成出來的二維碼怎麼掃都識別不了
2.想到了在線api去生成,網上搜索有很多,我選擇了兩個帶https的

https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=http://www.baidu.com(未備案)
https://sapi.k780.com/?app=qr.get&data=http://www.xsyrz.cn&level=L&size=15(已備案)

過程中遇到以下幾個問題
1.canvas繪製網絡圖片 在真機上不生效 需先下載至本地
2.下載二維碼圖片至本地時 在後臺配置合法域名時 提示未備案域名不可以
3.用已備案的地址生成二維碼 用canvas繪製出來時太過模糊 掃不出來 將size加大
4.url路由中含有#號 生成時不識別具體路徑 嘗試UrlEncode編碼的方式

小程序中繪製canvas並將其生成圖片保存在本地

// 繪製canvas
  showModal(){
    this.setData({
      isHelp:true,
    })
    let self = this;
    let ctx = wx.createCanvasContext('shareImg')
    let headImg = wx.getStorageSync('headImg'); // 分享首圖
    let codeImg = wx.getStorageSync('codeImg'); // 二維碼
    ctx.fillStyle = "white";
    ctx.fillRect(0, 0, 350, 400); // 繪製白色背景
    ctx.drawImage(headImg, 0, 0, 350, 260); // 繪製首圖
    ctx.fillStyle = 'black';
    ctx.fillText(this.data.NickName + ' 喊你幫TA砍價', 20, 300); // 繪製黑色文字
    ctx.drawImage('../../img/logo2.png', 20, 320, 45, 15);  // 繪製logo
    ctx.drawImage(codeImg, 180, 270, 75, 75)
    ctx.draw(false, function () {
      // 將canvas生成圖片 必須在draw回調中執行
      wx.canvasToTempFilePath({
        x: 0,
        y: 0,
        width: 350,
        height: 450,
        destWidth: 700,
        destHeight: 900,
        canvasId: 'shareImg',
        success(res) {
          console.log(res.tempFilePath)
          self.setData({
            shareImgSrc: res.tempFilePath
          })
        },
        fail(err) {
          console.log(err)
        }
      })
    });
  },

小程序保存網絡圖片和本地圖片到相冊

  saveImage() {
    // 如果是網絡圖片 需先下載至本地
    wx.downloadFile({
      url: this.data.shareImgSrc,
      success(res) {
        console.log(res.tempFilePath)
        // 如果已生成本地圖片路徑 可直接到這一步保存
        wx.saveImageToPhotosAlbum({
          filePath: res.tempFilePath,
          success(res) {
            wx.showToast({
              title: '保存成功'
            });
          },
          fail(err) {
            console.log(err)
          },
        })
      },
    })
  },

日期格式帶 - 的話在ios不生效 需用.replace(/-/g, '/')將其轉成 / 

小程序中如何清除計時器?如何清除多個計時器?

1.data中定義timer爲數組格式
2.每創建一個計時器 用this.data.timer.push(timer)
3.onHide和onUnload生命中週期中循環遍歷timer去清除
for (let i = 0; i < this.data.timer.length; i++) {
  clearInterval(this.data.timer[i])
}

小程序中如何阻止事件冒泡?和h5有什麼區別?

舉例:外層容器有點擊事件進入詳情 容器內包含按鈕 點擊後只想調提醒接口而不進詳情 
現象:傳統的bindtap點擊了內部按鈕 外部事件也會隨之觸發
解決:內部按鈕的提醒事件用catchtap
和h5阻止事件冒泡的區別:
$("button").click(function(event){
  event.stopPropagation();
  alert("The button element was clicked.");
});
$("div").click(function(){
  alert("The div element was clicked.");
});

小程序web-view頁面 分享出去 打開空白

原因分析:分享時微信對url進行了編碼 導致打不開

解決辦法:onLoad中對url進行解碼處理  url: decodeURIComponent(options.url)

用戶拒接保存相冊權限後怎樣重新打開

問題出現:項目中有一個向用戶本地相冊保存圖片的權限 默認進來會打開彈框提示 是否授權 用戶點擊同意 成功保存 但點擊拒絕之後 再次保存就沒辦法了 官網查詢解釋如下:

所以 原有的wx.authorize重新獲取授權的方法並不能成功(網上很多人說的這種)

解決辦法:wx.openSetting調起小程序設置界面 引導用戶再次打開權限(但是現在好像官方好像不允許通過代碼去執行了,需要用戶通過點擊事件去執行)

<button open-type="openSetting" bindopensetting='handler'>點擊授權保存相冊權限</button>

小程序中如何上傳圖片到阿里雲oss

參考文檔:
https://blog.csdn.net/tang05709/article/details/80712107
https://help.aliyun.com/document_detail/92883.html?spm=a2c4g.11186623.6.1378.144149e8jsNag6

需求描述:

用戶通過小程序上傳圖片到阿里雲服務器(oss對象存儲),拿到對應的鏈接地址後,通過接口傳給後臺。

解決方案:

1.登錄阿里雲管理控制檯,配置 Bucket 跨域,設置允許跨域訪問

2.登錄小程序管理後臺,配置uploadFile合法域名,加入外網域名

3.下載上傳demo,upload.js中配置accessid、accesskey、host,並打印new_multipart_params參數

4.通過html測試上傳圖片 控制檯裏拿到key、policy、OSSAccessKeyId、signature等參數

(以上四步參考文檔裏都有,講的很詳細,可以對照看一下)

5.小程序中拿取照片並上傳,代碼如下

// 上傳照片
  upload(e) {
    let self = this;
    wx.chooseImage({
      success: function (res) {
        let imgSrc = res.tempFilePaths[0];
        let fileType = imgSrc.split('.')[imgSrc.split('.').length-1];
        let folderName = 'app-contract/test/';
        let key = folderName + new Date().getTime() + '.' + fileType;
        let imgUrl = 'https://tb-images.oss-cn-shenzhen.aliyuncs.com/' + key
        wx.uploadFile({
          url: 'https://tb-images.oss-cn-shenzhen.aliyuncs.com',
          filePath: imgSrc,
          name: 'file',
          formData: {
            'name': imgSrc,
            'key': key,
            'policy': 'xxxxx',           
            'OSSAccessKeyId': 'xxxxx',
            'signature': 'xxxxx',           
            'success_action_status': '200',
          },
          success: function (res) {
            console.log(res)
            self.uploadImage(imgUrl);
          },
          fail: function (res) {
            console.log(res)
          },
        })
      }
    })
  },

 微信單擊雙擊事件並存

<image mode='aspectFill' data-url='{{item}}' src="{{item}}" bindload="swiperHeight" style='width:100%;height:100%;' bindtap='multipleTap' bindtouchstart="touchStart" bindtouchend="touchEnd"></image>
  // 按鈕觸摸開始觸發的事件
  touchStart(e) {
    this.touchStartTime = e.timeStamp
  },
  // 按鈕觸摸結束觸發的事件
  touchEnd(e) {
    this.touchEndTime = e.timeStamp
  },
// 單擊預覽圖片 雙擊心動
  multipleTap(e) {
    var self = this
    // 控制點擊事件在350ms內觸發,加這層判斷是爲了防止長按時會觸發點擊事件
    if (self.touchEndTime - self.touchStartTime < 350) {
      // 當前點擊的時間
      var currentTime = e.timeStamp
      var lastTapTime = self.lastTapTime
      // 更新最後一次點擊時間
      self.lastTapTime = currentTime
      // 如果兩次點擊時間在300毫秒內,則認爲是雙擊事件
      if (currentTime - lastTapTime < 300) {
        console.log("雙擊事件被觸發")
        // 成功觸發雙擊事件時,取消單擊事件的執行
        clearTimeout(self.lastTapTimeoutFunc);
        wx.showModal({
          title: '示愛成功',
          content: '對方將會收到您的心動提示',
          showCancel: false
        })
        self.setData({
          isLove:true
        })
      } else {
        // 單擊事件延時300毫秒執行,這和最初的瀏覽器的點擊300ms延時有點像。
        self.lastTapTimeoutFunc = setTimeout(function () {
          console.log("單擊事件被觸發")
          wx.previewImage({
            current: e.currentTarget.dataset.url, // 當前顯示圖片的http鏈接
            urls: self.data.bannerList // 需要預覽的圖片http鏈接列表
          })
        }, 300);
      }
    }
  },

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章