如何查询网站是否有内存泄漏问题
1.使用谷歌浏览器打开网站,并打开控制台,切换到Memory(内存)菜单下
2.以核医学项目为例,查看核医学病例管理页面到报告页面是否存在内存泄漏问题
1)打开病例管理页面
2)点击内存释放按钮释放内存
3)点击生成快照按钮生成当前快照
4)双击病例列表进入报告页面,在报告页面做一些操作后,关闭报告页面回到病例管理页面,并重复上述2、3步骤
5)多次重复上述2、3、4步骤生成多次快照,对比每次快照生成的当前内存大小去比较,如果每次内存都会明显增加,说明存在内存泄漏问题
该图片用作案例,可看出内存并未出现明显增加,说明并未出现内存泄漏问题
6)如果出现内存泄漏问题,可通过对比前后两次内存快照查看哪些地方存在内存泄漏,并且点击开可查看具体代码位置
选择查看那两个的对比清空
第七次到第八次内存对比情况
常见的内存泄漏问题,以及怎么避免内存泄漏
1)项目内使用vue-easytable 1.x 的地方切换成 iviewTable
2) 项目内使用ztree组件的地方切换成使用iviewTree
3) setTimeout/setInterval 在页面销毁时必须要释放
data(){
return {
time1: '',
time2: ''
}
},
mounted(){
this.time1 = setInterval(() => {
// 代码
})
},
methods: {
fun1() {
// 再次执行前要停用上次的定时操作
clearInterval(this.time2 )
this.time2 = setInterval(() => {
// 代码
})
}
},
// 组件销毁前生命周期,释放所有当前组件的定时器
beforeDestroy() {
clearInterval(this.time1);
clearInterval(this.time2);
}
4)组件内在window、docuemnt、$EventBus上面监听的事件要在销毁的时候移除
data(){
return {
time1: '',
time2: ''
}
},
mounted(){
window.addEventListener('keydown', this.fun1) // 必须要传入一个具名函数
document.addEventListener('keydown', this.fun2) // 必须要传入一个具名函数
$(window).resize(this.fun3) // jQuery 事件监听,必须要传入一个具名函数
this.$EventBus.$on('name', ()=>{})
window.nodeApi.oncenew('winclose', this.fun4); // nodeApi的事件监听
},
methods: {
fun1() {},
fun2() {},
fun3() {},
fun4() {}
},
// 组件销毁前生命周期,移除监听事件
beforeDestroy() {
window.removeEventListener('keydown', this.fun1) // 和添加事件的时候传入同一个方法
document.removeEventListener('keydown', this.fun2) // 和添加事件的时候传入同一个方法
$(window).off('resize', this.fun3) // jQuery 事件监听,和添加事件的时候传入同一个方法
this.$EventBus.$off('name') // 销毁时name的值要与创建的一致
window.nodeApi.removeListener('winclose', this.fun4); // 移除nodeApi的事件监听
}
5)组件内的websocket连接要在销毁的时候移除
data(){
return {
socketInstance:''
}
},
mounted(){
this.socketInstance = new WebSocket('url');
this.socketInstance.onopen = function (evt) {}
this.socketInstance.onerror = function (evt) {}
this.socketInstance.onmessage = function (evt) {}
this.socketInstance.onclose = function (evt) {}
},
methods: {
},
// 组件销毁前生命周期,移除socket连接
beforeDestroy() {
this.socketInstance.onopen = null
this.socketInstance.onmessage = null
this.socketInstance.onclose = null
this.socketInstance.onerror = null
this.socketInstance.close();
this.socketInstance = null;
}
6) 避免代码逻辑报错
function fun1(params) {
/*如果不确保参数一定是字符串*/
/*错误写法*/
params.split()
/*正确写法*/
if (typeof params === 'string') {
params.split()
}
}
7)其他建议
//禁止给window对象赋值
window.a = {}
window.onclick = function(){}
// 绝大部分情况下不要使用原生js获取dom元素
document.querySelector(".class") // 原生js获取dom
$(".class") // jQuery获取dom
// 非必要不用定时器,可以使用nextTick代替
// 错误代码
setTimeOut(()=>{
//代码
},0)
// 正常代码
this.$nextTick(()=>{
//代码
})
// websocket、zmq等监听事件建议在全局监听,然后通过自定义事件分发,避免频繁的创建连接
// 新建websocket.js
export default function(){
this.socketInstance = new WebSocket('url');
this.socketInstance.onopen = function (evt) {}
this.socketInstance.onerror = function (evt) {}
this.socketInstance.onmessage = function (evt) {
window.dispatchEvent(
new CustomEvent('自定义名称', data)
)
}
this.socketInstance.onclose = function (evt) {}
}
// main.js
import myWebsocket from 'websocket.js' // 全局引入
myWebsocket() // 全局创建连接
// 组件内监听
mounted(){
window.removeEventListener('自定义名称', this.fun1) // 保证传入具名函数,方便后续移入监听
},
methods: {
fun1(data){}
},
// 组件销毁时移除事件监听
beforeDestroy{
window.removeEventListener('自定义名称', this.fun1); // 和监听是传入同一个具名函数
}