小程序中生命周期鈎子函數之外的全局變量要小心使用!!!


之前做的上傳水印這塊的功能。

有時候由於網絡過慢,重復點擊的話可能會導致重復打包(生成照片包)。本身做法可以在請求的過程中可以讓button禁用,這個就不多討論。

我當時臨時采用的是利用一個變量來控制,請求發出前把變量全局變量isSaving變成true,然后再按鈕的點擊事件剛進來的時候判讀,如果isSaving是true的話那么就return。

saveAndShare(){
    if(isSaving){
      return
    }
    let files = this.data.files;
    let _this = this;
    if(files.length == 0){
      wx.showModal({
        content: '請上傳照片!',
        showCancel: false,
        success: function (res) {
          if (res.confirm) {
            _this.chooseImage()
          }
        }
      })
      return
    }
    if(!this.data.title){
      wx.showModal({
        content: '請填寫標題',
        showCancel: false,
        success: function (res) {
          _this.setData({
            titleFocus:true
          })
        }
      })
      return
    }
    //驗證是不是上傳圖片后面時才加的水印,這里需要重新攔截處理
    //無需考慮復雜操作,只考慮同款水印,要么都有,要么沒有。

    //第一步:驗證圖片路徑有沒有水印信息。
    if (!files[0].includes('x-oss-process') && _this.data.encodeWord){
      console.log('執行')
      for(let i = 0;i<files.length;i++){
        files[i] += '?' + _this.data.urlHead + _this.data.encodeWord + _this.data.urlFoot;
      }
    }
    let uid = wx.getStorageSync('id');
    let contentList = [];
    let creator = null;
    for(let i = 0;i < files.length;i++){
      contentList.push({
        sequence:i,
        path: files[i].replace(_this.data.host,'')
      })
    }
    if (app.globalData.userInfo){
      creator = app.globalData.userInfo.nickName;
    }
    isSaving = true
    wx.request({
      url: util.head+'/mp/pr/img/package',
      method: 'POST',
      data: {
        uid,
        watermark: _this.data.word,
        title: _this.data.title,
        notes: _this.data.note,
        creator,
        contentList,
        contentNum: _this.data.files.length
      },
      success: function (res) {
        console.log(res.data)
        if (res.data.status == 'SUCCESS'){
          let id  = res.data.data;
          let creator = app.globalData.userInfo.nickName;
          let face = _this.data.files[0].split('?')[0];
          let title = _this.data.title
          wx.showToast({
            title: '打包成功',
            icon: 'success',
            duration: 1000,
            success: function () {
              setTimeout(function () {
                wx.reLaunch({
                  url: `/pages/msg/msg?id=${id}&creator=${creator}&face=${face}&title=${title}`,
                })
              }, 800)
            }
          })
        }else{
          isSaving = false;
          wx.showToast({
            title: '打包失敗',
            icon: 'none',
            duration: 1000
          })
        }
      }
    })
  },
  /**

其實這里我的漏洞是打包成功后應該把變量還原的。但是考慮到成功后會relauch跳轉到消息頁。

根據官方的路由說明,重啟動路由方式執行后,當前的這個上傳頁面會unload掉。

包括我進入了消息頁之后(消息頁是非Tab頁),然后用switchTab進入了列表頁(第二個tab選項),再重新切到第一個tab選項,再點擊navigate進入回到上傳頁面,一系列操作后,

講道理頁面第一步的時候已經卸載掉了,重新進入也是執行onload的,但是為什么isSaving還是true呢?

原因分析:小程序考慮到內存問題的情況下,所以在不同的路由情況會卸載路由前的頁面,以緩解內存壓力,但是可能這種不是完全的釋放內存,Unload卸載的是page對象內的一系列東西,包含data以及鈎子函數。

  但是由於isSaving是寫在page外面的全局變量,還是存在於微信緩存中的,所以頁面卸載后再重新加載,它的值始終是沒有重置的。

以下是isSaving的寫法:

另外重新試了下,var聲明的isSaving 只是相對於組件的全局變量,我在打包成功后的跳轉到的消息頁page中打印是以下結果:

 

總結:對於自己的的沒有處理好數據導致的小Bug,對小程序的人認識又增進一步真的是喜憂參半。大家對於小程序的page鈎子函數,頁面unload的理解要多注意,分辨出page之外定義的偽全局變量帶來的影響。

追述:小程序page函數,app對象之外的變量類似為頂級變量。需要小程序退出(后台5分鍾或者內存超標)才會注銷。根據小程序的模塊化概念可以單獨抽離出js文件,再結合生命周期概念,小程序中定義的頁面這一概念來配合對應的onload,onshow,unload等鈎子,針對的是page整個對象,所以即使這個a變量和page函數是寫在一個wx.j文件里,但我們不能就看成是綁定在一起的整體,事實上頁面的卸載是執行的清理掉對應的page對象,而不是釋放整個js文件。所以a的值會始終保持一個狀態!

ps:以上只是自己的想法和推測,希望路過的大神能多多指正!  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM