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中禁止使用。可以考虑使用防抖队列。

猜你喜欢

转载自www.cnblogs.com/anrainie/p/13163594.html