iview select 内存泄漏_Vue遇到的内存泄漏排查处理
Vue遇到的内存泄漏排查处理1.定位问题跟踪具体那一部分造成的泄漏。(1)js写法(闭包、全局变量等)、dom事件监听、循环定时器等这些造成的泄漏在度娘上应该都很好找到处理;(2)组件的泄漏(DOM泄漏即DOM无法销毁)导致DOM上挂载的事件,对象数组等的数据也跟着无法释放。2.排查方法。利用谷歌浏览器调试工具的内存快照,找到使你内存增加的业务场景(如打开某个组件内存上升,关闭该组件时内存却没有.
Vue遇到的内存泄漏排查处理
1.定位问题跟踪具体那一部分造成的泄漏。
(1)js写法(闭包、全局变量等)、dom事件监听、循环定时器等这些造成的泄漏在度娘上应该都很好找到处理;
(2)组件的泄漏(DOM泄漏即DOM无法销毁)导致DOM上挂载的事件,对象数组等的数据也跟着无法释放。
2.排查方法。
利用谷歌浏览器调试工具的内存快照,
找到使你内存增加的业务场景(如打开某个组件内存上升,关闭该组件时内存却没有释放下降),截取两段快照(如第一段为组件打开前,第二段为组件关闭后),对比内存大小这样就可以知道这个组件打开一次造成了多少内存泄漏。
选择第二段快照,右边选择Comparison,比对。
由上图可以看到,VueComponent组件
新增了#New 137
释放了#Deleted 0
泄漏值 137 – 0 = 137 泄漏了 137个组件
泄漏内存大小Alloc Size 3286 B 字节
释放的内存 Freed Size 0 B 字节
同理也可以观察其他部分的情况,比如Object Array 有多少新增,释放了多少,泄漏了多少。
重:我们最终还是要注意VueComponent的泄漏值,因为VueComponent是会挂载对象、数据、事件的,所以那些Object Array产生泄漏值也很大可能是VueComponent造成的。所以我们在处理泄漏的时候最好是先保证VueComponent的泄漏值为0. 然后再去往js闭包、循环定时器、事件监听那些方向去走。
顺着上图,可以往下展开看看,鼠标悬停,就可以看到是哪个Dom节点没有被销毁了($el,$elm),
3.销毁DOM、组件的方法
应该只能是v-if才有显著效果。
4.如果还是很难排查,那只能用注释代码的方式,注释,截快照比对,定位哪一块Dom产生的。
本人遇到的内存泄漏问题:
Modal弹窗,内部业务组件查询处理数据,关闭弹窗,内存无法释放。
当时定位到iview的Modal本身是有内存泄漏的,所以Modal里面的那些dom自然也不会得到释放,内存就会积压。因此总部处理了iview组件Modal的泄漏问题。
其他地方的泄漏:Modal里面嵌套了很多 子业务组件,而且有些是组件不得已用v-show展示,(因此,性能开销不大的时候还是要用v-if控制展示组件)
所以这边另外还需要多做其他处理:
- Modal要统一放到子组件里面,modal就不用v-if, 通过父组件的v-if来控制 modal弹出关闭(虽然modal放里放外看着是一样的效果,但是在处理内存问题时这么做确实可以让内存下降);
Modal外层包一个div,在子组件beforeDestroy的时候remove。This.$refs.xxxxx.remove();
(这个可能不是很有必要,但是没效果的时候可以这么试试,强制移除dom元素的意思)
- 子组件beforeDestroy的时候,把变量置null,(那些用来渲染页面的数据量大的Object、Array等;也可以全部置null包括dom绑定的事件)
- 父组件要传值给子组件的props变量,在关闭时,能置空的尽量置空。(比如那些在打开弹窗时要重新赋值传给子组件的变量)
- 代码优化,比如watch部分,也会有可能导致父组件一直watch挂载着导致子组件没有被销毁。(这个还是有必要的)
- Ztree本身有泄漏,调用API手动销毁。(这个可以优化一点点但是Ztree本身还是有泄漏但影响应该不大)
- 子组件嵌套组件避免太深,太多层级。
- 递归渲染,原本在测试环境内存增量已经控制在了0.1M-0.3M,但是扔到现场数据量大的时候,内存还是飙升无法下降,最后还是通过注释这个递归渲染在现场环境发现问题,去掉了递归渲染。(所以这个递归渲染可能存在着隐藏的什么问题,比如死循环,多出来的渲染回收不掉,还有待验证。),原本怀疑是table组件的问题,因为table组件有泄漏而且数据量最多的也是在渲染table,但是把table的渲染注释扔到现场并没有效果,于是顺着这个方式找到了递归渲染的问题。
- 子组件如果又有业务组件需要用v-show控制(并且要通过onClick、onSelect等重新查询数据渲染的),要在它的外层div加个v-if控制。
如:
this.ifShow = false;
this.$nextTck().then(() => { // 这个表示dom状态更新完成之后
this.ifShow = true;
// 这里再去查询重新渲染
})
小结:
整个过程的思路最开始是排查js部分,也花了好多时间,因为js有用到递归处理数据,当时数据也蛮多,所以最开始怀疑的是这个,后面接着是其他同事帮忙排查了一会发现是有些DOM没有被销毁,再后面就定位到了Modal组件有泄漏。刚处理完modal的问题时再去测发现效果也不是明显,最终是同事一句话是最重要的核心,就是如果组件内部也就是modal内部的某些元素或者某些组件有泄漏的话,是会影响到整个modal里边无法释放,所以后面就跟着这个思路,重点处理dom为何没有销毁,让dom(Vuecompenent)的泄漏值下降(销毁OM)。才慢慢定位了问题出在哪一部分。而销毁DOM的核心其实还是使用v-if,remove方法跟变量置null都是辅助的,要看具体的处理效果。递归渲染是有可能多出很多循环遍历导致产生很多无法销毁的DOM。
更多推荐


所有评论(0)