小程式中遇到observer函式引起的記憶體洩漏咋整?沒想到這麼簡單

梭梭醬加油鴨發表於2019-03-27

先來感受一下程式碼,報錯報的簡直扎心。

Component({
  /**
   * 元件的屬性列表
   */
  properties: {
    index: {
      //當這裡為number 時,拼串的0會被忽視,所以不可以為Number
      type: String,
      //當我們改變了index的值時,小程式主動來呼叫observer
      //並傳遞三個值:新值、舊值、路徑
      //observer裡
      observer: function (newVal, oldVal, changedPath) {
        let val = newVal<10 ? "0" + newVal : newVal
        console.log(val)
        this.setData({
          index: val
        })
      }
      }
  },

  /**
   * 元件的初始資料
   */
  data: {
    year: "",
    month: ""
  },
  
  attached: function(){
    const months = {
      0 : "一月",
      1 : "二月",
      2 : "三月",
      3 : "四月",
      4 : "五月",
      5 : "六月",
      6 : "七月",
      7 : "八月",
      8 : "九月",
      9 : "十月",
      10 : "十一月",
      11 : "十二月",
    }
    let date = new Date
    let year = (date.getFullYear()).toString()
    let monthN = (date.getMonth()).toString()
    let monthS = months[monthN]
    this.setData({
      year: year,
      month: monthS
    })
  },

  /**
   * 元件的方法列表
   */
  methods: {
    
  }
})

複製程式碼

總結下原因:observer函式是在data發生改變時小程式主動呼叫的,在observer函式內setData時又再次改變了properties的值,observer函式再次呼叫,不停的迴圈……無限遞迴呼叫……於是記憶體耗盡。

那麼問題來了,為啥type為Number時不會發生記憶體洩漏?

本質上就是因為properties值根本沒變。當外部改變index值為A(假如),觸發observer函式時,函式內部將傳進來的值進行拼串後,由於值的型別設定為Number,拼串後的值0A會按照數字解析成A,所以進入函式內部後這個值繞了一圈還是沒變,所以不會無限遞迴呼叫observer.

解決辦法:

看到記憶體洩漏、遞迴這些字眼是不是就怕怕的?莫方(說給自己聽)。

既然observer內部改變properties內部資料會產生問題,那麼,我們們就不改變唄!曲線救國。在data裡設定一個變數_index,把拼串後的值給到_index就好啦!注意在wxml中也要把繫結的資料改為{{_index}}。完美~

程式碼如下:

// components/epsoide/index.js
Component({
  /**
   * 元件的屬性列表
   */
  properties: {
    index: {
      //當這裡為number 時,拼串的0會被忽視,所以不可以為Number
      type: String,
      //當我們改變了index的值時,小程式主動來呼叫observer
      //並傳遞三個值:新值、舊值、路徑
      //observer裡
      observer: function (newVal, oldVal, changedPath) {
        let val = newVal<10 ? "0" + newVal : newVal
        this.setData({
          _index: val
        })
      }
      }
  },

  /**
   * 元件的初始資料
   */
  data: {
    year: "",
    month: "",
    _index: ""
  },

  attached: function(){
    const months = {
      0 : "一月",
      1 : "二月",
      2 : "三月",
      3 : "四月",
      4 : "五月",
      5 : "六月",
      6 : "七月",
      7 : "八月",
      8 : "九月",
      9 : "十月",
      10 : "十一月",
      11 : "十二月",
    }
    let date = new Date
    let year = (date.getFullYear()).toString()
    let monthN = (date.getMonth()).toString()
    let monthS = months[monthN]
    this.setData({
      year: year,
      month: monthS
    })
  },

  /**
   * 元件的方法列表
   */
  methods: {
    
  }
})
複製程式碼

最後!!!千萬不要嘗試在observer函式裡改變properties的值!!!

相關文章