mpvue開發微信小程序踩坑

  1. 在列表page點擊進入詳情頁面時,用onShow()方法 去獲取數據去展示數據,因爲onShow方法會在比mounted()執行更快。由於小程序的緩存很嚴重,所以在返回的時候如果不將data中定義的數據清除的話,再次點擊進入詳情頁面的話,還是會顯示第一次進入詳情頁的數據,可以在methods中寫一個初始化數據的方法
  initData() {
    this.videoFlag = false //是否顯示視頻
    this.classDes = {}
    this.promotionData = {}
    this.activeIndex = 0
    this.classDetailData = null
    this.classId = null
    this.isShow = false
    this.networkType = 'wifi'
    this.classVideoData = {}
 }

需要在onUnload()或者onHide()函數中調用這個方法,這樣才能保證下次進來會展示新的數據
2. 在請求數據的時候,我們選用flyio.js來進行數據的請求獲取,所以我們會對請求方法進行二次封裝,在封裝的時候我們會加入一個微信原生提供的loading方法(wx.showLoading())方法用於在請求接口時的等待顯示,感覺用戶體驗會更好。這樣做在其他請求頁面請求接口還好,但是在列表頁面下拉加載時,


onPullDownRefresh() {
  this.refreshClassList();
},
refreshClassList() {
  wx.request({
    success: res => {
      ...
      wx.hideLoading();
      wx.stopPullDownRefresh();
    }  
  })
}

由於小程序提供下拉刷新方法,所以使用原生的下拉刷新方法,但是下拉回彈的動畫總是會過度回彈,導致頂部元素被遮擋,同時多次下拉會有機率觸發頁面卡下來的bug,通過goole,百度,確認是兩個loading共用導致,小程序的下拉刷新有頂部動畫效果,所以下拉刷新時不需要做wx.showLoading的提示,最終在列表頁面決定去掉wx.showLoading提示
3. 微信小程序在最新版將不再提供默認彈出授權窗口,需要用戶去點擊觸發才能彈出授權窗口,經過商討,我們決定在添加一個授權頁面,在app.vue的onLaunch()方法中判斷是否授權,如果沒有授權將跳到授權頁面,點擊按鈕進行授權,反之,則繼續執行正常操作
4. 我們在寫組件的時候,往往會用到slot插槽,但是在嵌套組件中使用slot插槽無法正常顯示渲染,最終在mpvue的Issues中找到解決辦法,要在[email protected][email protected][email protected]的環境下嵌套組件的slot纔可以正常使用。目前已降級到指定版本,暫時沒有發現bug。
5. 在項目中有用到城市聯級選擇的情景,當時選用mpvue-picker插件來開發,因爲聯動需要循環,第一級或者第二級改變都需要遍歷一遍數組,省市可能數據量比較大,然後就出現了卡頓,所以棄用,然後又找到了mpvue-citypicker,這個插件將citypicker單獨出來,改變了城市數據結構,沒有出現卡頓現象。
6. 小程序分享朋友圈功能,首先請求後端生成的小程序碼(生成小程序碼需要access token,後端生成比較方便),要使用小程序碼的圖片路徑,如果直接使用的話使用canvas是畫不上去的,必須要通過wx.downloadFile這個api先把圖片下載到本地,拿到臨時路徑

wx.getImageInfo({
          src: _this.GenerateQrcode,
          success: function(res) {
            const background = '/static/canvas/canvas.png'
            const GenerateQrcode_s = res.path
            console.log(GenerateQrcode_s)
            wx
              .createSelectorQuery()
              .select('.box')
              .boundingClientRect(function(rect) {
                const {
                  user,
                  title,
                  price,
                  teacher,
                  configs1,
                  configs2,
                  content,
                  message
                } = _this.friendCircleParam
                const shareModule = wx.createCanvasContext('shareCanvas')
                const { width, height } = rect
                const canvas_w = width * wx.getSystemInfoSync().windowWidth / 400 // 375
                const canvas_h = height * wx.getSystemInfoSync().windowWidth / 380
                const centerX = canvas_w / 2
                const rpx = _this.rpxchange // rpx

                // 初始化 canvas寬度
                _this.shareCanvasWidth = `width:${canvas_w}px;height:${canvas_h}px;`
                // 繪製背景
                shareModule.drawImage(background, 0, 0, canvas_w, canvas_h)
                // 繪製分享人
                shareModule.setTextAlign('center')
                shareModule.setFontSize(rpx(24))
                shareModule.setFillStyle('#FFFFFF')
                shareModule.fillText(user, centerX, rpx(48 + 24 + 6))
                // 繪製文案
                shareModule.setFontSize(rpx(60))
                shareModule.setFillStyle('#FCE9A7')
                shareModule.fillText(title, centerX, rpx(106 + 36 + 16))
                // 繪製價格
                shareModule.setFontSize(rpx(28))
                shareModule.setFillStyle('#FFFFFF')
                shareModule.fillText(price, centerX, rpx(216 + 28))
                shareModule.setStrokeStyle('#fff')

                shareModule.beginPath();
                shareModule.arc(rpx(210) + rpx(20), rpx(210) + rpx(20), rpx(20), Math.PI, Math.PI * 3 / 2);
                shareModule.lineTo(rpx(200) - rpx(20) + rpx(210), rpx(210));
                shareModule.arc(rpx(200) - rpx(20) + rpx(210), rpx(20) + rpx(210), rpx(20), Math.PI * 3 / 2, Math.PI * 2);
                shareModule.lineTo(rpx(200) + rpx(210), rpx(48) + rpx(210) - rpx(20));
                shareModule.arc(rpx(200) - rpx(20) + rpx(210), rpx(48) - rpx(20) + rpx(210), rpx(20), 0, Math.PI * 1 / 2);
                shareModule.lineTo(rpx(20) + rpx(210), rpx(48) +rpx(210));
                shareModule.arc(rpx(20) + rpx(210), rpx(48) - rpx(20) + rpx(210), rpx(20), Math.PI * 1 / 2, Math.PI);
                shareModule.closePath();
                // shareModule.strokeRect(rpx(220), rpx(200), rpx(200), rpx(20))
                // shareModule.fillText(price, centerX, rpx(220 + 38))
                // 繪製描述
                shareModule.font = `bold ${rpx(36)}px PingFangSC-Semibold`
                shareModule.setFillStyle('#000')
                _this.drawText(
                  shareModule,
                  content,
                  centerX,
                  rpx(340 - 42),
                  canvas_w * 0.9,
                  rpx(50)
                )
                // 繪製老師
                shareModule.font = `normal ${rpx(24)}px PingFangSC-Semibold`
                shareModule.setFillStyle('#888888')
                // shareModule.fillText(teacher, centerX, rpx(410 + 24 + 6))
                _this.drawText(
                  shareModule,
                  teacher,
                  centerX,
                  rpx(410 - 60),
                  canvas_w * 0.7,
                  rpx(30)
                )
                // 繪製中間提示文案
                shareModule.font = `normal ${rpx(26)}px PingFangSC-Semibold`
                shareModule.setFillStyle('#FF6d73')
                shareModule.fillText(configs1, centerX, rpx(450 + 54 + 6))
                shareModule.font = `normal ${rpx(26)}px PingFangSC-Semibold`
                shareModule.setFillStyle('#FF6d73')
                shareModule.fillText(configs2, centerX, rpx(480 + 74 + 6)) shareModule.drawImage(_this.GenerateQrcode, centerX, rpx(584), rpx(252), rpx(250))
                console.log(_this.GenerateQrcode)
                shareModule.drawImage(
                  GenerateQrcode_s,
                  canvas_w * 0.3,
                  rpx(594),
                  rpx(200),
                  rpx(200)
                )
                // 長按識別小程序碼,一起省錢!
                shareModule.setFontSize(rpx(26))
                shareModule.setFillStyle('#Afafaf')
                shareModule.fillText(message, centerX, rpx(824 + 28 + 8))
                // line
                shareModule.stroke()
                shareModule.draw()
                wx.hideLoading()
              })
              .exec()
          },
          fail: function(err) {
            wx.hideLoading()
            wx.showToast({
              title: '生成失敗,請重新嘗試',
              icon: 'none',
              duration: 3000,
              mask: true
            })
          }
        })

_this.GenerateQrcode是從後臺活動的小程序二維碼,如果需要背景圖的話,需要在本地保存一張圖片當做背景圖。切記不能使用線上圖片,不起作用。
識別圖片跳轉到小程序相關頁面時,需要在生成圖片傳遞需要的參數,參數要在scene中傳遞。但是有些頁面需要多個參數纔可以打開,但是scene中只能傳遞一個參數,所以我們將參數用一個特殊符號拼接起來,比如

   var par = `${this.$root.$mp.query.activityId}_${
          this.$root.$mp.query.classId
        }_${this.$root.$mp.query.isLive}`
        
        this.GenerateParam = {
          // 小程序二維碼參數
          scene: par,
          page: `pages/activityInfo/components/activityDetail`,
          width: 250,
          auto_color: false,
          line_color: { r: '236', g: '66', b: '76' },
          is_hyaline: true
        }

在對應的頁面

onLoad(options) {
      var that = this
      
      if (options.scene) {
        that.scene = decodeURIComponent(options.scene)
        var arr = that.scene.split('_')
        that.getPara = arr
        console.log('value', arr)
      }
    },

用split()方法將參數分割成數組,在去拿對應的參數就可以了

7.mpvue在npm run build的後在ios 9中會如下的錯:

Page[pages/index/main] not found. May be caused by: 1.forgot to add page route in app.json. 2.Invoking Page{} in async task.

thirdScriptError
sdk uncaught third error
SyntaxError
line:16045,column:0,SynataxError:Unexpected keyword 'const'. Const declarations are not supported in strict mode. Stack:

報這個錯得原因是因爲我們的項目安裝了mpvue-wxparse這個插件,因爲微信小程序不能像vue一樣用v-html解析帶有html標籤的數據,所以我們安裝了這個插件。解決這個報錯的方法是在webpack.base.conf.js文件中把

{
        test: /\.js$/,
        include: resolve('src'),
        use: [
          'babel-loader',
          {
            loader: '@f-loat/mpvue-loader',
            options: {
              checkMPEntry: true
            }
          },
        ]
      },

替換成

{ 
        test: /\.js$/,
        include: [resolve('src'), resolve('test'), /mpvue-wxparse/], 
        use: [ 
          'babel-loader', 
          { 
            loader: '@f-loat/mpvue-loader',
            options: { 
              checkMPEntry: true 
            } 
          }, 
        ] 
      }

就可以成功的解決這個bug了。
8.
8. 真機和模擬器的問題總結

  • input 標籤中設置爲placeholder屬性,縮進樣式text-indent在模擬器中失效,在真機上可以的,但是value值是不起作用的,只能用padding-left來進行縮進了
  • 測試過程中,域名爲http格式的請求,在模擬器下可以正常運行,在真機中必須打開調試才能看到效果
  • 由於video組件調用的是客戶端創建的原生組件,它的層級是最高的,模擬器中不會出現這個問題,而真機中會覆蓋其他的內容,要使用對應的cover-view標籤或者cover-image標籤
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章