常见原因
https://juejin.im/post/5cb33660e51d456e811d2687
1.意外的全局变量
2.被遗忘的计时器或回调函数
echart
- echarts只初始化一次,找不到echarts实例再去初始化,而不是每次都销毁再初始化
if(HistoryChart['alarmevent_Num_chart']){
HistoryChart['alarmevent_Num_chart'].dispose();
}
HistoryChart['alarmevent_Num_chart'] = echarts.init(document.getElementById('alarmevent_Num_chart'));
改成
if(!HistoryChart['alarmevent_Num_chart']){
HistoryChart['alarmevent_Num_chart'] = echarts.init(document.getElementById('alarmevent_Num_chart'));
}
three.js
- scene.remove()不要在for..in,或者forEach中执行
正确方式
for (let index = scene.children.length-1;index>=0;index--){
scene.remove(scene.children[index]);
}
这是因为three.js 内部是用splice来删除,删除完后索引会发生变化,有些对象就无法被删除,所以应该从数组尾部删除
- geometry,material,material.map要执行dispose 方法否则不会被删除
可以用traverse方法遍历
scene.children[i].traverse(v=>{
if (v.geometry) {
v.geometry.dispose();
}
if (v.material) {
v.material.dispose &&
v.material.dispose();
if (v.material.map) {
v.material.map.dispose &&
v.material.map.dispose();
}
}
})
【补充】20210804
还需要注意的是,UI给的3D模型变了,material.map有可能是一个数组,原先的代码需要做一些调整
// 释放材质
function disposeMaterial(v) {
v.material.dispose &&
v.material.dispose();
if (v.material.map) {
v.material.map.dispose &&
v.material.map.dispose();
}
}
scene.children[i].traverse(v=>{
if (v.geometry) {
v.geometry.dispose();
}
if (v.material) {
// 修改点开始
if (Array.isArray(v.material)) {
v.material.forEach(vv=>{
vv.map && vv.map.dispose()
vv.dispose()
})
} else {
disposeMaterial(v)
}
// 修改点结束
}
})
VUE
- beforeDestroy
如果有引用第三方库需要特别注意,在执行的时候,页面已经跳转到下一个页面了,document指向的是下一个页面的文档对象,就没有办法获取到要清理的dom节点了
正确方式
// 使用ref
this.$refs.main_model.removeChild(renderer.domElement)
- 如果有使用echarts
this.chart && this.chart.dispose()
- 如果有使用定时器
clearInterval(this.timer)
I18N
- 额。。。当初国际化写法不当导致内存泄漏被扣了好多钱,
但是现在一点都想不起是怎么写的了。。。