Vue Web App 內存泄漏-調試和分析


一、寫在前面

js中的內存垃圾回收機制:垃圾回收器會定期掃描內存,當某個內存中的值被引用為零時就會將其回收。當前變量已經使用完畢但依然被引用,導致垃圾回收器無法回收這就造成了內存泄漏。傳統頁面每次跳轉都會釋放內存,所以並不是特別明顯。

Web App 與 傳統Web的區別,因為Web App是單頁面應用頁面通過路由跳轉不會刷新頁面,導致內存泄漏不斷堆積,導致頁面卡頓。

二、泄漏點

  1. DOM/BOM 對象泄漏
  2. script 中存在對DOM/BOM 對象的引用導致
  3. Javascript 對象泄漏
  4. 通常由閉包導致,比如事件處理回調,導致DOM對象和腳本中對象雙向引用,這個時常見的泄漏原因

三、代碼關注點

  1. DOM中的addEventLisner 函數及派生的事件監聽, 比如Jquery 中的on 函數, vue 組件實例的 $on 函數,第三方庫中的初始化函數
  2. 其它BOM對象的事件監聽, 比如websocket 實例的on 函數
  3. 避免不必要的函數引用
  4. 如果使用render 函數,避免在html標簽中綁定DOM/BOM 事件

四、如何處理

  1. 如果在mounted/created 鈎子中綁定了DOM/BOM 對象中的事件,需要在beforeDestroy 中做對應解綁處理

  2. 如果在mounted/created 鈎子中使用了第三方庫初始化,需要在beforeDestroy 中做對應銷毀處理

  3. 如果組件中使用了定時器,需要在beforeDestroy 中做對應銷毀處理

  4. 模板中不要使用表達式來綁定到特定的處理函數,這個邏輯應該放在處理函數中?

  5. 如果在mounted/created 鈎子中使用了$on,需要在beforeDestroy 中做對應解綁($off)處理

  6. 某些組件在模板中使用 事件綁定可能會出現泄漏,使用$on 替換模板中的綁定

如何在vue 組件中處理addEventListener

created/mounted 生命期鈎子函數中定義事件響應函數為對象實例的方法,使用 => 函數來綁定作用域
   調用 addEventListener 添加事件監聽
   beforeDestroy 中調用 removeEventListener 移除對應的事件監聽,注意前面定義的響應函數方法需要作為第二個參數傳入
   然后用 delete 從對象實例移除定義的響應方法,或者將屬性設置為 null/undefined

為什么不能使用匿名函數或者已有的函數的綁定來直接作為事件監聽函數

  這樣無法准確移除監聽,函數每次綁定返回的是不同的函數實例

具體例子請參考 如下代碼

mounted() {
    const box = document.getElementById('time-line')
    this.width = box.offsetWidth
    this.resizefun = () => {
      this.width = box.offsetWidth
    }
    window.addEventListener('resize', this.resizefun)
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.resizefun)
    this.resizefun = null
  }


免責聲明!

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



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