1>意外的全局变量
函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放。

2>未清除的定时器
定时器没有清除,它内部引用的变量,不会被释放。

3>脱离DOM的元素引用
一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。

4>持续绑定的事件
函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。

5>绑在EventBus的事件没有解绑

6>闭包引起内存泄漏
比如事件处理回调,导致DOM对象和脚本中对象双向引用。

7>使用第三方库创建,没有调用正确的销毁函数

8>单页应用时,页面路由切换后,内存未释放

JavaScript 有完善的内存处理机制,能自动进行垃圾回收,但是假如一个对象一直被引用,他的内存是无法得到释放的。如果项目运行过程中,内存占用越来越高,只增不减,没有峰值,就存在内存泄漏。多页应用我们可以通过页面刷新缓解,但是对于服务端渲染和单页应用则需要重点关注内存泄漏问题。本文主要以Vue单页应用展开,因为在 SPA 的设计中,用户使用它时是不需要刷新浏览器的,所以 JavaScript 应用需要自行清理组件来确保垃圾回收以预期的方式生效。

一、什么是内存泄漏
程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。对于持续运行的服务进程,必须及时释放不再用到的内存。否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。不再用到的内存,没有及时释放,就叫做内存泄漏。

二、如何判断内存泄漏
Chrome 浏览器memory有3种方式,可以分析内存:

Heap snapshot - 用以打印堆快照,堆快照文件显示页面的 javascript 对象和相关 DOM 节点之间的内存分配

Allocation instrumentation on timeline - 在时间轴上记录内存信息,随着时间变化记录内存信息。

Allocation sampling - 内存信息采样,使用采样的方法记录内存分配。此配置文件类型具有最小的性能开销,可用于长时间运行的操作。它提供了由 javascript 执行堆栈细分的良好近似值分配。

三、如何定位内存泄漏
点击快照-并hover右测的列表项,会显示部分存在内存泄漏的地方

四、常见的内存泄漏
意外的全局变量
函数中意外的定义了全局变量,每次执行该函数都会生成该变量,且不会随着函数执行结束而释放。

未清除的定时器
定时器没有清除,它内部引用的变量,不会被释放。

脱离DOM的元素引用
一个dom容器删除之后,变量未置为null,则其内部的dom元素则不会释放。

持续绑定的事件
函数中addEventListener绑定事件,函数多次执行,绑定便会产生多次,产生内存泄漏。

绑在EventBus的事件没有解绑

闭包引起内存泄漏
比如事件处理回调,导致DOM对象和脚本中对象双向引用。

使用第三方库创建,没有调用正确的销毁函数

单页应用时,页面路由切换后,内存未释放

五、解决内存泄漏
变量先申明后使用。

setTimeout setInterval清理 (最好不用)可以使用nextTick代替。

如果在mounted/created 钩子中绑定了DOM/BOM 对象中的事件,需要在beforeDestroy 中做对应解绑处理。

 1 mounted () {
2 window.addEventListener('resize', this.onResize)
3 },
4 beforeDestroy () {
5 window.removeEventListener('resize', this.onResize)
6 }
7 如果在mounted/created 钩子中使用了on,需要在beforeDestroy 中做对应解绑(off)处理。
8 mounted () {
9 this.$EventBus.$on('exitClassRoom',this.exitClassRoomHandle)
10 },
11 destroyed () {
12 this.$EventBus.$off('exitClassRoom',this.exitClassRoomHandle)
13 }

如果在mounted/created 钩子中使用了第三方库初始化,需要在beforeDestroy 中做对应销毁处理。
慎用keep-alive
当你用 keep-alive 包裹一个组件后,它的状态就会保留,因此就留在了内存里,切莫在整个路由页面上加上keep-alive。
一旦你使用了 keep-alive,那么你就可以访问另外两个生命周期钩子:activated和 deactivated。你需要在一个 keep-alive 组件被移除的时候,调用 deactivated 钩子进行清理或改变数据。

六、实际案例
教师工作台是单页应用,在来回切换路由时,页面耗用内存在一直上升。

通过全局搜索,发现部分事件没有解绑,部分添加代码如下

按照上面的1-5方法解决后,内存耗用还是在增长,怀疑不是组件内部的问题,从头开始读代码,发现问题:keep-alive绑定在了整个router-view上,而且代码写得很不友好,路由不同router-view也不同,代码如下:

 1 <keep-alive>
2 <el-container class="teacher-content" v-if="
3 ['teacherWorkbenchCourse', 'teacherWorkbenchReschedule'].indexOf(
4 this.$router.currentRoute.name
5 ) === -1
6 " key="teacher-content">
7 <el-header class="body-banner">
8
9 <Banner>
10 <DhProductLineSelect v-if="this.$router.currentRoute.name == 'teacherWorkbench'"></DhProductLineSelect>
11 <template v-if="
12 this.$router.currentRoute.name == 'personMaterial' ||
13 this.$router.currentRoute.name == 'contentCloud'
14 ">
15 <BreadCrumbMaterial></BreadCrumbMaterial>
16 </template>
17 <template v-if="
18 this.$router.currentRoute.name == 'searchResult' || this.lessonIsEdit">
19 <span class="router-go-back">
20 <img src />
21 </span>
22 </template>
23 <template v-if="!this.lessonIsEdit">
24 <BreadCrumbs />
25 </template>
26 </Banner>
27 </el-header>
28 <el-main class="body-main">
29
30 <router-view></router-view>
31 </el-main>
32 </el-container>
33
34 <router-view v-else> </router-view>
35 </keep-alive>
36 优化后:
37
38 <el-container
39 class="teacher-content"
40 key="teacher-content"
41 >
42 <el-header class="body-banner" :class="[headClass, marginLeft]">
43
44 <Banner>
45 <DhProductLineSelect v-if="this.$router.currentRoute.name == 'teacherWorkbench'||this.$router.currentRoute.name=='teacherWorkbenchCourse'"></DhProductLineSelect>
46 <template
47 v-if="
48 this.$router.currentRoute.name == 'personMaterial' ||
49 this.$router.currentRoute.name == 'contentCloud'
50 "
51 >
52 <BreadCrumbMaterial></BreadCrumbMaterial>
53 </template>
54 <template
55 v-if="
56 this.$router.currentRoute.name == 'searchResult' || this.lessonIsEdit"
57 >
58 <span class="router-go-back">
59 <img src />
60 </span>
61 </template>
62
63 <template v-if="!this.lessonIsEdit">
64 <BreadCrumbs/>
65 </template>
66 </Banner>
67 </el-header>
68 <el-main :class="['body-main',mainNoPadding]">
69 <router-view></router-view>
70 </el-main>
71 </el-container>

综上操作,内存耗用截图如下,无用内存大部分得到释放:

vue中处理过内存泄露处理方法的更多相关文章

  1. iPhone应用中如何避免内存泄露?

    如何有效控制iPhone内存管理的对象的所有权与引用计数和以及iPhone内存的自动释放与便捷方法.本文将介绍在iPhone应用中如何避免内存泄露.想了解“在iPhone应用中如何避免内存泄露”就必须 ...

  2. Java宝典(四)------Java中也存在内存泄露。

    --Java中会存在内存泄露吗? --如果你想当然的以为Java里有了垃圾回收机制就不会存在内存泄露,那你就错了. Java里也会存在内存泄露! 我们慢慢来分析. 所谓内存泄露就是指一个不再被程序使用 ...

  3. 对开发中常见的内存泄露,GDI泄露进行检测

    对开发中常见的内存泄露,GDI泄露进行检测 一.GDI泄露检测方法: 在软件测试阶段,可以通过procexp.exe 工具,或是通过任务管理器中选择GDI对象来查看软件GDI的对象是使用情况. 注意点 ...

  4. Flex内存泄露解决方法和内存释放优化原则

    Flex内存泄露解决方法和内存释放优化原则 你对Flex内存泄露的概念是否了解,这里和大家分享一下Flex内存释放优化原则和Flex内存泄露解决方法,希望本文的介绍能让你有所收获. Flex内存释放优 ...

  5. vue中使用echarts的两种方法

    在vue中使用echarts有两种方法一.第一种方法1.通过npm获取echarts npm install echarts --save 2.在vue项目中引入echarts 在 main.js 中 ...

  6. vue中push()和splice()的使用方法

    vue中push()和splice()的使用方法 push()使用 push() 方法可向数组的末尾添加一个或多个元素,并返回新的长度.注意:1. 新元素将添加在数组的末尾. 2.此方法改变数组的长度 ...

  7. Android开发中常见的内存泄露案例以及解决方法总结

    1.单例模式引起的内存泄露 由于单例模式的静态特性,使得它的生命周期和我们的应用一样长,如果让单例无限制的持有Activity的强引用就会导致内存泄漏如错误代码示例: public class Use ...

  8. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  9. 谈谈.NET中常见的内存泄露问题——GC、委托事件和弱引用

    其实吧,内存泄露一直是个令人头疼的问题,在带有GC的语言中这个情况得到了很大的好转,但是仍然可能会有问题.一.什么是内存泄露(memory leak)?内存泄露不是指内存坏了,也不是指内存没插稳漏出来 ...

随机推荐

  1. word-制作三线表

    找一个表格或插入一个表格, 找到 [设计] [新建表格样式] [将格式应用于: 整个表格] 点击"框线设置"按钮,在弹出的下拉菜单中分别选择 [上框线] 和 [下框线],然后分别设 ...

  2. 几百行代码实现一个 JSON 解析器

    前言 之前在写 gscript时我就在想有没有利用编译原理实现一个更实际工具?毕竟真写一个语言的难度不低,并且也很难真的应用起来. 一次无意间看到有人提起 JSON 解析器,这类工具充斥着我们的日常开 ...

  3. Future源码一观-JUC系列

    背景介绍 在程序中,主线程启动一个子线程进行异步计算,主线程是不阻塞继续执行的,这点看起来是非常自然的,都已经选择启动子线程去异步执行了,主线程如果是阻塞的话,那还不如主线程自己去执行不就好了.那会不 ...

  4. 从0到1建设智能灰度数据体系:以vivo游戏中心为例

    作者: vivo 互联网数据分析团队-Dong Chenwei vivo 互联网大数据团队-Qin Cancan.Zeng Kun 本文介绍了vivo游戏中心在灰度数据分析体系上的实践经验,从&quo ...

  5. .NET Core 实现后台任务(定时任务)IHostedService(一)

    原文链接:https://www.cnblogs.com/ysmc/p/16456787.html 最近有小伙伴问道,在 .Net Core 中,如何定时执行任务,而因为需要执行的任务比较简单,并不想 ...

  6. 攻防世界MISC—进阶区32—37

    32.normal_png 得到一张png,扔进kali中binwalk 和 pngcheck一下,发现CRC报错 尝试修改图片高度,我是把height的2改为4,得到flag 33.很普通的数独 得 ...

  7. java包机制

  8. 记一次 .NET 某电厂Web系统 内存泄漏分析

    一:背景 1. 讲故事 前段时间有位朋友找到我,说他的程序内存占用比较大,寻求如何解决,截图就不发了,分析下来我感觉除了程序本身的问题之外,.NET5 在内存管理方面做的也不够好,所以有必要给大家分享 ...

  9. 5-2 SpringCloud | 微服务

    服务器端项目演进 服务器初期状态 最早的服务器就是安装部署了一些静态页面 功能非常单一,只能做信息的呈现和输出 服务器动态页面 后来因为业务和技术的发展,页面连接了数据库,页面中大部分数据来自于数据库 ...

  10. Note -「Dsu On Tree」学习笔记

    前置芝士 树连剖分及其思想,以及优化时间复杂度的原理. 讲个笑话这个东西其实和 Dsu(并查集)没什么关系. 算法本身 Dsu On Tree,一下简称 DOT,常用于解决子树间的信息合并问题. 其实 ...