小程序開發技巧總結

0.小程序如何請求設置頭信息

因爲在前一篇文章中寫過,這裏就不重複了。參考下面這個連接:

ASP.NET WebAPI 雙向token實現對接小程序登陸邏輯

下面這個連接是參考資料,直接參考這一篇就明白怎麼設置請求頭
jquery ajax 設置請求頭header參數php

1. 微信小程序引用同一js文件中的方法函數(function)

如上圖紅色框所示,引用同一js文件中的函數不像普通js調用,須要加上下面代碼段加粗部分。(不知道在代碼段裏面爲何不顯示粗體了,就是**這裏)html

onLoad: function (options) {
          **var that=this;**
          **this.loadList();**
    }, **loadList**:function(e){
    wx.request({
         url: app.globalData.apiurl + '/api/NoUploadBackBill',
         data: {
         mobile: app.globalData.phone,
         },
         header: {
        'content-type': 'application/json', // 默認值
        'Authorization': "BasicAuth " + util.getToken()
        },
        success(res) {
        console.log(res.data.length);
        }
       })
    },

2. 小程序中循環遍歷(即列表渲染)

個人需求是顯示返回的列表數據,頁面須要分條顯示。一般是要用js遍歷,但在小程序裏面,只須要返回數據集,在wxml頁面用wx:for綁定數組便可顯示。以下圖所示,使用wx:for後沒有提供wx:key會報一個warning,在這小節後面第一個連接是官方的文檔,裏面有提到【如不提供 wx:key,會報一個 warning, 若是明確知道該列表是靜態,或者沒必要關注其順序,能夠選擇忽略。】
前端

wxml頁面:
<view  wx:for="{{newBillList}}" wx:key="*this" class="list"></view>

該數組要在js文件的data內聲明。jquery

js文件:
聲明:
data: {
    newBillList: [], //要顯示的列表以及搜索操做後的列表
  },
  
賦值:
 loadList: function(e) { //發起請求,根據手機號加載未上傳回單
    wx.request({
      url: app.globalData.apiurl + '/api/NoUploadBackBill/Loading',
      data: {
        mobile: app.globalData.phone,
      },
      header: {
        'content-type': 'application/json', // 默認值
      },
      success: res => {
        if (res.data.length > 0) {
          var list = [];
          for (var i = 0; i < res.data.length; i++) {
            res.data[i].ImageList = [];
            list.push(res.data[i]);
          }
          this.setData({
            billList: list,
            **newBillList: list**
          });
        }
      },
      fail(res) {
        console.log("loadList fail:" + res.data);
      }
    })
  }

小程序-視圖層-WXML-列表渲染es6

小程序for循環web

3. 小程序js傳遞多個參數

小程序的js裏面和通用的js傳參同樣,經過全局變量傳遞,或函數參數傳遞。ajax

//調用處理列表圖片的方法
        this.addImageList(1, 0);
    
    //從新處理數據,把圖片列表加入
    addImageList: function (type, count) {}

4. this.setData is not a function

Page.prototype.setData(Object data, Function callback)數據庫

在微信小程序中,通常經過this.setData來修改值。好比在函數裏面修改數據,以下代碼段所示:search要在data內初始化json

searchinput: function (e) {//查詢輸入框賦值
    this.setData({
      search: e.detail.value
    })
  }

可是,當經過wx.request請求數據成功後綁定數據卻出現this.setData is not a function的錯誤。
小程序

//發起請求,根據手機號加載未上傳回單
    wx.request({
      url: app.globalData.apiurl + '/api/NoUploadBackBill',
      data: {
        mobile: app.globalData.phone,
      },
      header: {
        'content-type': 'application/json', // 默認值
      },
      success(res) {
        console.log(res.data);
         if(res.data.length>0){
           this.setData({
             billList: res.data
           });
         } 
      },fail(res){
        console.log("fail"+res);
      }
    })

爲何會出現這個error呢,我當時百思不得其解,也沒有想到做用域這一層,是查找資料才解決該問題。

緣由是由於:由於this做用域指向問題 ,success函數實際是一個閉包 , 沒法直接經過this來setData。

第一種方法:
var that=this;
this.setData({billList:res.Data});
第二種方法:
success:res=>{
     this.setData({billList:res.data})
   }

具體緣由要參考這個連接

參考資料:微信小程序中this指向做用域問題this.setData is not a function報錯

5. 小程序點擊控件隱藏一個View,顯示另外一個View

隱藏和顯示,必定明白是用樣式控制了。並且是在JS控制樣式,代碼段以下:

wxml頁面:
 <view  wx:for="{{billList}}" wx:key="*this" class="list" style="display:{{billdisplay}};" >
/**
   * 頁面的初始數據
   */
  data: {
    **billdisplay**:'block',//回單列表是否顯示
    **searchdisplay**:'none'//查詢列表是否顯示
  },
   searchList:function(e){//搜索事件
     var _this=this;
    //設置首次加載的回單列表隱藏,顯示查詢的列表
     _this.setData({
       billdisplay:'none',
       searchdisplay:'block'
     });
      
  }

後記:當時由於想法不完整,因此把顯示數據列表用兩個View表示,用樣式控制,但其實這兩個View顯示的內容是同樣的。後來經過初始化兩個數組,一個顯示查詢後的列表,一個是原始數據的列表,用兩個數組經過在使用中從新push數據,這樣解決了用兩個view處理的冗餘辦法。這個作法在第12點。

6. 小程序裏push的用法

在小程序裏面,在data裏初始化的變量是沒法直接push的。要在使用的時候另外聲明變量,push,最後再賦值。以下代碼段加粗部分(即有**的部分):

//從新處理數據,把圖片列表加入
  addImageList: function (type, count) {
    var that = this;
    **var listArr = [];//聲明一個可操做變量數組**

    for (let i = 0; i < this.data.newBillList.length; i++) {
      if (this.data.shipmentid == this.data.newBillList[i].ShipmetId) {
        //累加上傳的回單
        var cnt = this.data.newBillList[i].DocumentsCnt;
        count=count+cnt;
        let row = {
          ShipmetId: this.data.newBillList[i].ShipmetId,
          EarliestPickTime: this.data.newBillList[i].EarliestPickTime,
          FromAddress: this.data.newBillList[i].FromAddress,
          ToAddress: this.data.newBillList[i].ToAddress,
          DriverName: this.data.newBillList[i].DriverName,
          LicenseNumber: this.data.newBillList[i].LicenseNumber,
          DocumentsCnt: type == 1 ? this.data.newBillList[i].DocumentsCnt : count,
          ImageList:this.data.imageListArr
        }
        **listArr.push(row);**
      } else {
        let row = this.data.newBillList[i];
        **listArr.push(row);**
      }
    }
    //賦值
    that.setData({
      //顯示列表
      **newBillList: listArr**
    });
  },

參考資料
小程序push數組報錯解決辦法

7. 小程序獲取view的ID

wxml頁面:
<button catchtap="removeImg" class="button_img" type="default" id="{{image}}"   data-shipmentid="{{item.ShipmetId}}">移除</button>
js頁面:
 //直接獲取ID
 var viewId = e.target.id;
 console.log(viewId);
 //獲取data-shipmentid
 var shipmentid=e.target.dataset.shipmentid;
  console.log(shipmentid);

原本想貼一下官方的api有關e.target以及e.current.target的資料,可是突然搜索不出來.....

8. 字符串拼接值(官方叫字符串運算)

這裏比較簡單,又易理解,直接貼官方的代碼

<view>{{"hello" + name}}</view>
Page({
  data:{
    name: 'MINA'
  }
})

9. 引入util.js出錯



如上圖所示,我當前開發中的文件目錄以下:
pages/business/nouploadbackbill/nouploadbackbill,
我在js文件中引用util.js的時候,我覺得能夠這樣的:

const util = require('../../utils/util.js')

可是,實際上彷佛要根據當前開發文件的目錄結構引用

//引用
const util = require('../../../utils/util.js')

不知道是否是這樣理解,若有誤導或錯誤請指正批評~

10. 小程序remove元素

沒有remove,無法remove,只能經過操做數組處理。代碼段參考第6點以及第12點

11. 小程序獲取上級元素

當時的問題是這樣的,由於有一個view有id,而後view裏有一個button,這個button事件須要取到view的id進行移除操做,須要標識是移除哪個view。
可是後現發現,view能夠不用給id屬性,button能夠直接給id屬性,直接用它本身的id值判斷就能夠操做。
代碼參考第7點。

12. 小程序全部頁面路徑都要放在app.json

當時我之前在app.json文件配置的都是主頁。主頁裏面跳轉的頁面沒必要配置。直到報錯才知道全部頁面都要放在app.json裏面配置。否則運行的時候會報not in app.json。以下圖所示:

13. 小程序操做動態循環的數據

由於顯示列表裏面還有一個圖片列表的數組,該列表有一個上傳圖片和移除圖片操做,上傳圖片就把圖片push到這個圖片數組,而後從新push列表顯示,移除也同樣,把要移除的圖片從列表裏排除,從新push列表顯示。

如下這段代碼很是重要!由於正是看到了如下這段代碼,我遇到的難題得以解決,感恩碰見,哈哈

因爲這個連接是在小程序社區看到的,因此兩個連接都貼出來,參考連接以下:

for (var i = 0; i < this.data.newBillList.length; i++) {
      if (e.target.dataset.id == this.data.newBillList[i].shipmentid) {
        newBillList[i] = {
          id: this.data.newBillList[i].id,
          price: this.data.newBillList[i],
          one2one: this.data.newBillList[i],
        }
      } else {
        txtArray1[i] = {
          id: this.data.liuliangItems[i].id, changeColor: false,
          price: this.data.liuliangItems[i].price, name: this.data.liuliangItems[i].name,
          one2one: this.data.liuliangItems[i].one2one
        }
      }
    }

小技巧系列

微信小程序點擊button或view後選中其它反選

個人數據有三次循環量,由於在從一個循環列表裏面操做兩個循環。暫且說它是複合循環吧。當時困我好多天的難題用如下這段代碼解決,快誇我~哈哈

//移除圖片,按id移除
  removeImg: function(e) {
    var that = this;
    var listArr = [];
    var imgArr = [];
    for (var i = 0; i < this.data.newBillList.length; i++) {
      if (e.target.dataset.shipmentid == this.data.newBillList[i].ShipmetId) { //相等的當前選中的數據,移除列表的圖片的須要從新組合數據
        for (var j = 0; j < this.data.newBillList[i].ImageList.length; j++) {
          //第一種寫法
          if (e.target.id != this.data.newBillList[i].ImageList[j]) { //相等的值是要移除的值,不做處理
            imgArr.push(this.data.newBillList[i].ImageList[j]); //從新push圖片

          }
          //第二種寫法,es6的寫法
          //let id = e.target.id;
          //this.data.newBillList[i].ImageList[j].splice(id,1);//刪除 //splice(index,count) 第一個參數是索引,第二個參數是刪除的個數

        }
        //把數據從新push
        var row = {
          ShipmetId: this.data.newBillList[i].ShipmetId,
          EarliestPickTime: this.data.newBillList[i].EarliestPickTime,
          FromAddress: this.data.newBillList[i].FromAddress,
          ToAddress: this.data.newBillList[i].ToAddress,
          DriverName: this.data.newBillList[i].DriverName,
          LicenseNumber: this.data.newBillList[i].LicenseNumber,
          DocumentsCnt: this.data.newBillList[i].DocumentsCnt,
          ImageList: imgArr
        }
        listArr.push(row);
      } else { //數據不變的是不用處理的列表塊,直接push
        var row = this.data.newBillList[i];
        listArr.push(row);
      }
    }

14. 小程序上傳文件wx.uploadFile

這一部分被我形容是第二難題。(固然,是針對我在本身當前開發的功能裏面~)
這裏分爲幾個部分:

wx.chooseImage({
      count: this.data.count[this.data.countIndex],
      sizeType: ['original', 'compressed'],
      sourceType: ['album', 'camera'],
      success: res => {
        // tempFilePath能夠做爲img標籤的src屬性顯示圖片
        this.setData({
          shipmentid: e.target.dataset.shipmentid,
          imageListArr: res.tempFilePaths
        })
        //調用處理列表圖片的方法
        this.addImageList(1, 0);//該函數完整代碼在第6點
      },
      fail: function(data) {
        wx.showToast({
          title: "選擇圖片出錯",
          icon: "none",
          duration: 1000
        });

      }
    });
//預覽圖片
  previewImage: function(e) {
    let current = e.target.dataset.src;
    let imageList = [];
    for (let i = 0; i < this.data.newBillList.length; i++) {
      if (e.target.dataset.shipmentid == this.data.newBillList[i].ShipmetId) {
        imageList = this.data.newBillList[i].ImageList;
      }
      wx.previewImage({
        current: current, //當前顯示圖片的連接
        urls: imageList //須要預覽的圖片連接列表
      })
    }
  },

這裏要說一下,我這邊的需求是先把圖片上傳到開發者服務器,而後再從開發者服務器把圖片讀取保存到另外一個系統所在的服務器上。讀取圖片的時候不用下載圖片,我上傳圖片的時候會在數據庫一個表保存圖片的相關信息,列表id,圖片名稱,在開發者服務器的所在路徑等一些相關用到的字段。

第一步:先上傳圖片到開發者服務器,客戶端發起一個 HTTPS POST 請求,其中 content-type 爲 multipart/form-data

//上傳圖片,將本地資源上傳到開發者服務器
  uploadImage: function(e) {
    var that = this;
    that.setData({
      shipmentid: e.target.dataset.shipmentid
    });
    var listArr = [];
    var uploadImgCount = 0;
    var uploadArr = [];
    var imgLength = 0;
    for (var i = 0; i < this.data.newBillList.length; i++) {
      if (e.target.dataset.shipmentid == this.data.newBillList[i].ShipmetId) {
        imgLength = this.data.newBillList[i].ImageList.length;
        var index = i;
        console.log("列表的待上傳的回單數:" + imgLength);
        if (imgLength < 1) {
          wx.showToast({
            title: '沒有可上傳的回單',
            icon: 'none',
            mask: true,
            duration: 1000
          });
          var row = this.data.newBillList[i];
          listArr.push(row);
        } else {
          //啓動上傳等待中...
          wx.showToast({
            title: '正在上傳...',
            icon: 'loading',
            mask: true,
            duration: 10000
          });
          //遍歷圖片列表上傳
          for (var j = 0; j < this.data.newBillList[i].ImageList.length; j++) {
            //記錄當前列表的索引,由於到了success裏就獲取不到啦
            var index = i;
            //上傳圖片到開發者服務器
            wx.uploadFile({
              url: app.globalData.apiurl + '/api/NoUploadBackBill/PostImageFile',
              filePath: this.data.newBillList[i].ImageList[j], //要上傳文件資源的路徑
              name: 'image', // 這裏的具體值,要與後臺保持一致
              header: {
                'content-type': 'multipart/form-data',
                'Authorization': "BasicAuth " + util.getToken()
              },
              formData: { //HTTP 請求中其餘額外的 form data
                'shipmentid': this.data.shipmentid,
                'imgIndex': j //上傳的圖片編號(後臺提供給前端判斷圖片是否所有上傳完)
              },
              success: res => {
                //console.log("res:"+res.data);
                uploadImgCount++;
                uploadArr.push(res.data);

                //判斷是否上傳完畢
                if (uploadImgCount == imgLength) {

                  //顯示數據,調用處理列表圖片的方法,只修改所選運單的回單數便可
                  this.addImageList(2, uploadImgCount);
                  //保存操做的列表數到TMS數據表
                  let row = {
                    ShipmetId: this.data.newBillList[index].ShipmetId,
                    EarliestPickTime: this.data.newBillList[index].EarliestPickTime,
                    FromAddress: this.data.newBillList[index].FromAddress,
                    ToAddress: this.data.newBillList[index].ToAddress,
                    DriverName: this.data.newBillList[index].DriverName,
                    LicenseNumber: this.data.newBillList[index].LicenseNumber,
                    DocumentsCnt: uploadImgCount,
                    ImageList: uploadArr
                  }
                  this.setData({
                    saveImageList: row
                  });

                  //保存圖片到TMS
                  this.saveImage();

                }
              },
              fail: res => {
                console.log("uploadImage fail:" + res);
                wx.hideToast();
                wx.showModal({
                  title: '錯誤提示',
                  content: '上傳圖片失敗',
                  showCancel: false,
                  success: function(res) {}
                });

              }
            });
          }

        }

      }
    }
  }

這裏你們必定很關心個人後臺代碼是如何編寫的,我是參考第一個連接作的。

參考資料:
微信小程序實現圖片上傳功能

.NET WebAPI實現圖片上傳

第二步:把圖片從開發者服務器讀取並保存到另外一個服務器

這裏當時由於POST數據以及'content-type',還有JSON.stringify也卡住了很久(知識點不紮實)

//保存圖片
  saveImage: function(e) {
    //console.log("新json字符串:" + JSON.stringify(this.data.saveImageList));
    wx.request({
      url: app.globalData.apiurl + '/api/NoUploadBackBill/SaveImageFile',
      data: JSON.stringify(this.data.saveImageList),
      header: {
        'content-type': 'application/json',
        'Authorization': "BasicAuth " + util.getToken()
      },
      method: "POST",
      success: res => {
        console.log(" POST success:" + res.data.Message);
        if (res.data.Code == "0") {
          wx.showToast({
            title: '上傳成功',
            icon: 'none',
            mask: true,
            duration: 2000
          });
        } else {
          wx.showToast({
            title: '上傳圖片到服務器失敗:' + res.data.Message,
            icon: 'none',
            mask: true,
            duration: 2000
          });
        }
      },
      fail: res => {
        console.log("saveImage fail:" + res.data);
      }
    });
  },

這裏你們必定也會關心數據的轉換,這裏貼一下後臺代碼:

//接收參數爲dynamic類型
    public IHttpActionResult SaveImageFile(dynamic obj){
   var s = JsonConvert.SerializeObject(obj);
   //實例化一個可以序列化數據的類
   JavaScriptSerializer js = new JavaScriptSerializer(); 
   //將json數據轉化爲對象類型
   var entity = js.Deserialize<NoUploadBackBillModel>(s);  
   }

還有數據讀取以及保存,這裏使用文件流FileStream處理,從圖片轉換爲二進制流讀取,這裏是調用web service處理的。具體代碼不在我這邊,就沒有辦法貼出來啦~

參考連接:
WebAPI 接口參數

15. WebAPI 找到了與該請求匹配的多個操做

找到了與該請求匹配的多個操做的解決辦法

WebApi 找到了與該請求匹配的多個操做

WebAPI post傳遞參數二、實體做爲參數

16. 小程序自適應單位rpx

這個rpx我原來不知道是微信小程序推出了新尺寸單位。直到我作完功能測試發現沒有自適應。由於我在裏面慣性使用了px和em。後來看這個參考連接就所有改過來了,而後頁面在不一樣的設備不會溢出啦。參考連接以下:

細解小程序自適應單位rpx

最後,想說所遇到的問題點幾乎都通過查閱資料解決。在知識紅利的時代,你們無私分享本身的所學,在此很是感謝分享開發總結的夥伴。誠摯感謝!

相關文章
相關標籤/搜索