zoukankan      html  css  js  c++  java
  • 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中禁止使用。可以考虑使用防抖队列。

  • 相关阅读:
    常见的概念
    cas底层
    判断页面是否读取了缓存
    window.location.hash(hash应用)---跳转到hash值制定的具体页面
    * 输入框被第三方输入法遮挡问题
    Mui去掉滚动条:
    实用网址
    完美解决safari、微信浏览器下拉回弹效果。
    移动端兼容性问题解决方案
    监听ios自带返回功能
  • 原文地址:https://www.cnblogs.com/anrainie/p/13163594.html
Copyright © 2011-2022 走看看