什么是内存泄漏?
内存泄露(Memory Leaks):是指应用程序已经不再需要的内存,由于某种原因未返回给操作系统或者空闲内存池(Pool of Free Memory)。
内存泄露可能带来的问题:变慢、卡顿、高延迟。
内存泄漏的常见示例和防范
1.未能及时清除定时器
// 没去清除的定时器
setTimeout(this.someMethod, 1000)
setInterval(this.someMethod, 1000)
// 正确做法
this.timeout01 = setTimeout(this.someMethod, 1000)
this.interval01 = setInterval(this.someMethod, 1000)
// 在页面销毁的时候,及时清除
beforeDestroy() {
this.timeout01 && clearTimeout(this.timeout01)
this.interval01 && clearInterval(this.interval01)
}
2.未能及时取消事件的监听
bus.$on('aaa')
beforeDestroy() {
// 在页面销毁的时候,及时取消监听
bus.$off('aaa')
}
3.console.log 没有注释掉或在打包的时候没有清理掉造成泄漏
控制台日志记录对总体内存内置文件的影响,也是个重大的问题。记录错误的对象,可以将大量的数据保留在内存中。传递给console.log的对象是不能被垃圾回收,所以没有去掉console.log可能会存在内存泄漏
4.DOM创建造成内存泄漏
// 元素引用并没有清理
var a = document.getElementById('id');
document.body.removeChild(a);
// 不能回收,因为存在变量a对它的引用。虽然我们用removeChild移除了,但DOM元素还在内存里面。
解决方法: a = null;
5.变量没及时被清理,特别是对于数据量大的变量,要引起重视。
数据量过大:如果在VUE应用中处理了大量的数据,那么会导致内存占用较大。特别是在使用响应式数据时,当数据发生变化时,VUE会对其进行重新渲染,从而占用更多的内存。
methods: {
fun1() {
let a = [数据量可能会比较大的数组]
let b = [数据量可能会比较大的数组]
let c = [...a, ...b]
this.fun2(c)
// 此处应该用完就及时清理掉
a = null
b = null
c = null
},
fun2(data) {
// ......
}
}
6.如果应用中包含了大量的组件,每个组件都有自己的状态和响应式数据,那么会占用更多的内存。特别是在动态创建和销毁组件时,需要频繁地创建和销毁组件实例,从而导致内存占用较大。
解决办法:组件懒加载-将组件按需加载,只在需要的时候才加载组件,而不是一次性加载所有组件。
以下拿弹窗组件举个例子
// 页面中引入多个弹窗组件
<编辑与新增的组件/>
<拍照的组件/>
<打印的组件/>
// 由于以上组件在页面初始化的时候,是用不到的,点击相应的按钮后才会打开弹窗,这时候最好是加一个v-if判断
<编辑与新增的组件 v-if="isOpen01"/>
<拍照的组件 v-if="isOpen02"/>
<打印的组件 v-if="isOpen03"/>
// 然后对于Element-ui的el-dialog弹窗组件,有个属性要利用起来,关闭时销毁 Dialog 中的元素:destroy-on-close="true"
7.过多的循环嵌套,或者通过for、forEach等循环处理过于复杂的数据时所定义的变量没及时清理,也会导致内存用量飙升或者内存泄露的问题。平时也要合理使用循环遍历,尽可能减少遍历的次数。
总之,在日常开发的时候,细心点,及时规避会导致内存泄露的代码,就能开发出健康稳健的项目。