使用 iframe 发生内存泄漏
iframe 定义
依据 MDN(HTML(超文本标记语言) | MDN (mozilla.org))的定义:
HTML 内联框架元素 (<iframe>
) 表示嵌套的browsing context。它能够将另一个 HTML 页面嵌入到当前页面中。
每个嵌入的浏览上下文(embedded browsing context)都有自己的会话历史记录 (session history)和DOM 树。包含嵌入内容的浏览上下文称为父级浏览上下文。顶级浏览上下文(没有父级)通常是由 Window
对象表示的浏览器窗口。
iframe 使用示例
<iframe
id="iframe1"
src="https://cn.bing.com/"
frameborder="0"
width="100%"
height="300"
></iframe>
使用 iframe 的内存泄漏
在使用 iframe 时发现切换 iframe 页面 src 或者是关闭 iframe 页面时,iframe 相关的内存资源几乎没有释放掉。
切换 iframe 页面的内存泄漏
初始浏览器界面如下:
相关代码如下:
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<iframe
id="iframe1"
src="https://www.bing.com/"
frameborder="0"
width="500"
height="400"
></iframe>
</div>
<button onclick="changeIframeSrc()">切换</button>
</body>
<script>
let num = 0;
const arr = [
"https://www.baidu.com/home",
"https://zhidao.baidu.com/",
"https://www.hao123.com/?src=from_pc",
];
function changeIframeSrc() {
const iframe = document.getElementById("iframe1");
if (num === arr.length) {
num = 0;
}
iframe.src = arr[num];
console.log(111, iframe.src);
num++;
}
</script>
</html>
初始任务管理器如下:
点击几次切换按钮时,查看 windows 系统的任务管理器,
在切换过程中产生了内存泄漏。
解决步骤 1:
点击切换按钮时,在切换逻辑函数中,动态删除 iframe 和创建 iframe。
更改 changeIframeSrc 函数逻辑:
function changeIframeSrc() {
const box = document.getElementById("iframe_box");
const iframe = document.getElementById("iframe1");
box.removeChild(iframe);
//
if (num === arr.length) {
num = 0;
}
const iframeNew = document.createElement("iframe");
iframeNew.src = arr[num];
iframe.style = "width:500;height:400;";
box.appendChild(iframeNew);
num++;
}
初始任务管理器界面:
点击切换按钮几次,查看任务管理器:
发现还是有内存泄漏情况,接下来进行
解决步骤 2:
调用下文当中的 clearIframeFun 方法逻辑:
<script>
let num = 0;
const arr = [
"https://www.baidu.com/home",
"https://zhidao.baidu.com/",
"https://www.hao123.com/?src=from_pc",
];
function changeIframeSrc() {
const box = document.getElementsByClassName("iframe_box")[0];
clearIframeFun("iframe1");
//
if (num === arr.length) {
num = 0;
}
const iframeNew = document.createElement("iframe");
iframeNew.id = "iframe1";
iframeNew.src = arr[num];
iframeNew.frameborder = "0";
iframeNew.style = "width:500;height:400;";
box.appendChild(iframeNew);
num++;
}
function clearIframeFun(id) {
let element = document.getElementById(id);
element.src = "";
element.contentWindow.document.write(""); // 清空iframe内容 element.contentWindow.document.clear()
element.contentWindow.close(); // 避免iframe内存泄漏
element.remove(); // 删除iframe
document.body.removeChild(element);
}
</script>
大致思路就是切换 iframe 时清除掉上一个 ifarme 的相关资源。
关闭 iframe 页面的内存泄漏
开始浏览器界面是这样的,打开按钮出现 iframe 界面,关闭按钮去掉 iframe 界面:
以下资源占用情况是使用的 windows 的任务管理器查看的。
当点击关闭按钮没有调用 clearIframeFun 函数时,内存占用情况如下:
可见谷歌浏览器目前有 9 个进程,占用总的内存大概 200M,下面点击show iframe page按钮,浏览器界面如下:
查看任务管理器:
点击关闭按钮,查看任务管理器:
可见内存占用变少,主要原因是 iframe 元素去掉了,v-if (vue3)的作用:
<div class="iframe_box" v-if="iframeVisible">
<iframe
id="iframe1"
src="https://cn.bing.com/"
frameborder="0"
width="800"
height="500"
></iframe>
</div>
接下来使用下面的代码去掉内存占用:
const handleClose = () => {
iframeVisible.value = false;
let iframe: any = document.getElementById("iframe1");
clearIframeFun(iframe);
};
const clearIframeFun = (id: any) => {
let element: any = document.getElementById(id);
element.src = "";
element.contentWindow.document.write(""); // 清空iframe内容
element.contentWindow.document.clear();
element.contentWindow.close(); // 避免iframe内存泄漏
element.remove(); // 删除iframe
document.body.removeChild(element);
};
点击 show iframe page 按钮,任务管理器如下:
有 10 个进程,内存占用将近 300M。
点击 close iframe page 按钮,如下:
进程变成了 9 个,内存占用将近 200M,性能提升比较大。
一个 iframe 页面对应一个进程。