JS、VUE內存溢出問題的解決方案


1、學會使用devTool

參考文章

 

Memory詳解:

a、需要使用Memory來分析內存變化,至少記錄兩次內存快照,用於做內存變化比對。

image.png

 

舉例:

編輯器有內存溢出,所以在打開前記錄一次快照,打開編輯器等待加載完成,然后關閉編輯器,再記錄一次快照。

兩次快照間的內存差異,很大可能是內存溢出部分。當然,也有可能是一些依賴增長,此時多次打開關閉,觀察內存變化,持續累積的部分必然是內存溢出。

 

b、關注detachDomElement

 

detach的元素表示這些DOM元素不在DOM樹中,但是有被js對象所引用。

一般來說,這是內存溢出查找的主要入口。

image.png

 

查找的流程

1、找到shallow size較大的元素,一般來說會是HTMLDivElement,任意選中其中的一項,可以看到以下內容:

image.png

 

該清單表示它的被引用情況,此時,重點關注以下幾項:

1、用戶寫的對象

2、監聽

3、context上下文,上下文表示一些未被回收的函數中,有使用到相關對象

 

 

2、常見的解決方案

 

1 監聽的問題

很多開發者在使用觀察者模式后,忘了寫對應的注銷代碼,這是大忌。不論是js、jquery、vue還是自己寫的監聽,都必須有對應的注銷代碼。

 

有on就得有off。

有addListener就得有removeListener。

 

舉例:

在mounted的時候注冊的監聽,在beforeDestroy時候銷毀。

image.png

 

2、VUE本身的問題

 

VUE掛載了大量的對象,有可能因為用戶代碼的介入,導致無法銷毀,所以加入以下代碼:

 

const cleanVnode=vnode=>{  if(vnode){  vnode.elm = null;  vnode._renderChildren=null;  vnode.children=null;  // vnode.context=null;  vnode.componentOptions=null;  } }  Vue.mixin({  beforeDestroy() {  if(this.$el)  delete this.$el.__vue__;  },  destroyed() {  //為了內存,清空所有內容  this.$children = [];  this.$parent = null;  this._watchers = [];  this.$refs = {};  this.$root = null;  this.$slots = [];  this.$store = null;  cleanVnode(this._vnode);  cleanVnode(this.$vnode)  this._vnode = null;  this.$vnode = null;  if(this.$el)  delete this.$el.__ro__;  this.$el = null;  // this.$el=null;  this._watcher = null;  this._computedWatchers = {};  //ab-aui的內存溢出問題  this.popperElm=null;  if(this.$options){  this.$options.parent=null;  this._parentVnode=null;  this.$options=null;  }  }, }) 

 

需要注意,該代碼由於this.$el的銷毀,可能會造成一些bug。

 

 

3、全局對象的問題

 

a、減少全局對象的時候,關閉對象的時候,也要其銷毀在全局對象中的對應引用。

b、vue+全局對象可能有的觀察者(監聽)問題,vue會在對象中注冊__ob__,ob指的是observe,所以需要銷毀這些內容。推薦delete 全局對象.__ob__。

 

4、monacoEditor的問題

monacoEditor也有內存溢出問題,雖然它提供了dispose函數,但是我發現有時它銷毀不了所有對象。

自行銷毀方式如下:

//this.editor為MonacoEditor實例  this.editor && this.editor.dispose();  let config = this.editor._contentWidgets[  "editor.widget.suggestWidget"  ];  let x;  if ((x = config && config.widget)) {  x.dispose();  x.elememt = null;  x.editor = null;  x.list.dispose();  x.details.editor=null;  x.details.dispose();  for (let k in x) {  delete x[k];  }  }  for (let k in this.editor) {  delete this.editor[k];  }   this.editor = null;  this.__resize_ob = null;

 

5、VUE的computed中使用Vue.set的問題

Vue.set會觸發觀察,computed中禁止使用。可以考慮使用防抖隊列。


免責聲明!

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



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