記一次 Vue 組件內存泄漏的坑


概述

最近在開發 Vue 項目的時候遇到了內存泄漏問題,記錄下來,供以后開發時參考,相信對其他人也有用。

背景

背景是需要用 three.min.js 和 vanta.net.min.js 給首頁加上動畫效果。

內存泄漏

我們的代碼是這樣的:

mounted() {
  this.loadScript('/js/three.min.js', () => {
    this.loadScript('/js/vanta.net.min.js', () => {
      this.bannerBg = window.VANTA.NET({
        el: '#bannerBg',
        color: 0x2197F3,
        backgroundColor: 0x071E31,
      });
    });
  });
},
methods: {
  loadScript(path, callback) {
    const script = document.createElement('script');
    script.src = path;
    script.language = 'JavaScript';
    script.onload = () => callback();
    document.body.appendChild(script);
  },
},

這樣就導致,在每次首頁加載的時候,都會去請求 three.min.js 和 vanta.net.min.js 靜態資源,並且初始化。然后由於組件銷毀的時候並沒有清除 window.VANTA.NET 方法施加的內存,所以導致了內存泄漏。具體表現是,切換首頁和其它頁,切換的次數多了的話,就會卡住。

那一般的方法是直接在 beforeDestroy 生命周期里面 執行 this.bannerBg.destroy() 就行了。但是一開始我並不知道 this.bannerBg 帶有destroy 方法,所以走了下面的不少彎路。

檢查內存泄漏

按照官網的方法,Mac 下打開 Chrome 任務管理器的方式是選擇 Chrome 頂部導航 > 窗口 > 任務管理;在 Windows 上則是 Shift+Esc 快捷鍵。則可以打開 Chrome 的任務管理器,主要查看 Browser 和 GPU Process 的 內存占用空間。前者是查看程序執行所消耗的內存,后者是查看動畫效果所消耗的內存。

keep-alive

如果插件本身沒有提供 destroy 方法的話,可以使用官方的替代方案:使用 keep-alive 組件,在內存中保留組件的狀態。示例代碼如下:

<keep-alive>
  <my-component v-if="show"></my-component>
</keep-alive>

但是我實際使用下來,並沒有用,估計是因為 three.js 生成的 WebGL 動畫導致的不是 Browser 的內存泄漏而是 GPU 的內存泄漏吧。

如果這種方法不行的話,估計就真沒辦法避免內存泄漏了,幸好 vanta.net 其實暴露了 destroy 方法!

我看了下和這個場景比較相似的vue-particles源碼,它竟然沒有使用 destroy 釋放內存!!!

一個坑

在解決的過程中,我碰到了一個坑,就是我原本以為在 mounted 生命周期內的程序不會影響渲染,因為當執行到 mounted 生命周期的時候,Dom已經掛載好了。但是其實我錯了,如果在 mounted 生命周期里面執行一段非常耗時的代碼,瀏覽器是會一直白屏的,代碼示例如下:

mounted() {
  let a = 1;
  while (a < 123456) {
    console.log('aaaaa', a);
  }
}

原因我暫時不知道。。。。。。。。


免責聲明!

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



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