首页 前端知识 基于官方规范系列篇之——HTML 篇(七)iframe

基于官方规范系列篇之——HTML 篇(七)iframe

2025-03-10 12:03:23 前端知识 前端哥 831 725 我要收藏

大家好呀,我是前端创可贴。

上一章我们学习了关于 HTML 中视频的相关内容,相信大家对于现在的视频平台有了更多的认知。

这一章我们再一起来学习一下大名鼎鼎的 iframe。

iframe(The Inline Frame element)

iframe 元素表示一个嵌套的浏览上下文,它的内容可以是一个外部页面(通过 src 属性加载)或嵌入的 HTML(通过 srcdoc 属性定义)。

通过 iframe 我们可以非常方便的嵌入别的网页,不管是同源还是非同源,并且还可以限制它的行为和权限,以保证网页的安全。

我们可以将含有 iframe 元素的文档称为父文档(或者说父浏览上下文),iframe 元素渲染出来的文档称为子文档(或者说子浏览上下文)

src 属性

通过 src 属性可以指定 iframe 要加载的页面的 URL。

必须是一个有效且非空的 URL,可以包含空格(首尾的空格会被忽略)。

<iframe src="https://example.com"></iframe>
复制

与父文档同源的 iframe,在父文档可以读取到子文档的 DOM 和完整属性的 Window 对象等。

contentWindow

iframe 元素的 contentWindow 属性,返回 iframe 元素渲染的文档的 Window 对象。

  • 如果子文档与父文档是同源的,则该属性返回值的对象功能是不受限的,含有其全部属性以及访问 DOM 的权限。
  • 如果是跨域的,则返回的 Window 对象功能是受限的,很多属性以及访问 DOM 权限都是没有的。

对于含有 srcdoc 属性的 iframe 来说,没有设置 sandbox 的情况下,它与父文档永远是同源的。

同源 iframe 的 contentWindow 属性:

非同源 iframe 的 contentWindow 属性:

contentDocument

iframe 元素的 contentDocument 属性,返回 iframe 元素渲染的文档的 Document 对象。

  • 如果子文档与父文档是同源的,则该属性返回代表 iframe 元素的 Document 对象。
  • 如果是跨域的,则返回 null。

同源 iframe 的 contentDocument 属性:

非同源 iframe 的 contentDocument 属性:

parent

window 对象的 parent 属性,返回父文档的 Window 对象。

如果当前文档是最顶层,没有父文档,则 window.parent 返回当前文档的 window 对象。通常用于在 iframe 元素的文档中获取父文档的 window 对象。

  • 如果子文档与父文档是同源的,则该属性返回值的对象功能是不受限的,含有其全部属性以及访问 DOM 的权限。
  • 如果是跨域的,则返回的 Window 对象功能是受限的,很多属性以及访问 DOM 权限都是没有的。

当子文档与父文档是同源的时候,我们就可以通过 window.parent 与父文档通信,具体见后面的小节。

判断当前浏览上下文是否是 iframe,可以通过判断 parent === window,如果为 true,则说明不是 iframe;否则说明是 iframe。

<h1>前端创可贴</h1>
<iframe
srcdoc="<div>我是 iframe</div>
<script>console.log('iframe 内执行 parent === window 结果:', parent === window)</script>
"
frameborder="0"
></iframe>
<script>
console.log("父文档执行 parent === window 结果:", parent === window);
</script>
复制

srcdoc 属性

通过 srcdoc 属性,可以直接为 iframe 指定其嵌入页面的内容,而不是通过 URL 加载。

赋值 srcdoc 属性,会生成一个特殊的文档,URL 为 about:srcdoc

赋值的属性值必须要符合 HTML 语法,包含以下组成部分:

  1. 任意数量的注释和 ASCII 空白字符(如空格、换行)。
  2. 可选的 DOCTYPE 声明。
  3. 任意数量的注释和 ASCII 空白字符。
  4. 必须包含 html 元素作为文档的根。
  5. 任意数量的注释和 ASCII 空白字符。

<iframe srcdoc="
<!DOCTYPE html>
<html>
<head>
<title>Embedded Document</title>
</head>
<body>
<h1>Hello from srcdoc!</h1>
</body>
</html>
"></iframe>
复制

转义

由于 srcdoc 属性在 iframe 元素中是用 " 包裹的,而 srcdoc 属性值为 HTML 代码,也可能含有 ",所以属性值里的 " 必须先转义为 &quot;,否则会导致 srcdoc 属性提前结束。或者使用单引号来代替双引号。

<iframe srcdoc="<p title=&quot;Example&quot;>Hello, world!</p>"></iframe>
<iframe srcdoc="<p title='Example'>Hello, world!</p>"></iframe>
复制

文档结构简化

虽然 srcdoc 属性值是一段 HTML 代码,但并不必须是完整的 HTML 代码,对于 srcdoc 属性来说很多元素是可选的,没有存在的必要:

  • DOCTYPE 声明是可选的。
  • htmlheadbody 标签的起始与结束标记是可选的。
  • title 元素也是可选的。

由于许多元素是隐式存在的,所以其实只需要显式编写 body 元素里面的内容就可以了,所以 srcdoc 属性值可以非常简洁。

<iframe srcdoc="<div>前端创可贴</div>"></iframe>
复制

src 和 srcdoc 属性同时存在

如果同时指定了 srcsrcdoc 属性,srcdoc 属性优先级更高,浏览器会忽略 src 属性,加载并显示 srcdoc 中的嵌入内容。

src 属性会作为回退兜底,如果浏览器不支持 srcdoc 属性(例如旧版本浏览器),会加载 src 指定的 URL 作为回退内容。

<iframe
src="https://example.com/fallback.html"
srcdoc="<div>前端创可贴</div>"
sandbox>
</iframe>
复制

消耗资源

由于每一个 iframe 都是一个完整的 document 环境,也就是一个浏览上下文,所以每一个 iframe 都需要用到一些内存和计算资源,如果页面嵌套的 iframe 元素太多,可能会出现性能问题

我们来验证一下,我们页面放两个按钮,一个按钮点击后新增一个 iframe 元素,另外一个按钮新增 div 元素:

<h1>前端创可贴</h1>
<button id="btn1">创建 div</button>
<button id="btn2">创建 iframe</button>
<script>
let num = 1;
btn1.addEventListener("click", () => {
const div = document.createElement("div");
div.innerHTML = `我是 div${num++}`;
document.body.append(div);
});
btn2.addEventListener("click", () => {
const iframe = document.createElement("iframe");
iframe.srcdoc = `我是 iframe${num++}`;
document.body.append(iframe);
});
</script>
复制

我们打开浏览器的 Performance monitor 工具,看一下他们对 CPU 和内存的影响。

我们先来看看创建很多 div 元素对 CPU 和内存的影响:

可以看到,对 CPU 和内存几乎没什么影响。我们换成 iframe 再看一下:

可以看到,对 CPU 和内存的消耗还是比较明显的,我这里演示的 iframe 里的内容还特别少,更何况是复杂的页面,所以大家可以减少页面内嵌套 iframe 的使用,以减少内存,这对于移动端来说颇为重要

延迟主文档的 load 事件

嵌套的 iframe 元素加载了一个子文档,子文档中的资源、脚本等的加载会延迟子文档自己的 load 事件,也会延迟主文档的 load 事件子文档的 load 事件先触发,然后触发父文档的 load 事件

<!-- 父文档 -->
<h1>前端创可贴</h1>
<iframe src="./child.html" frameborder="0"></iframe>
<script>
window.addEventListener("load", () => {
console.log("父文档 load 事件");
});
</script>
复制
<!-- 子文档 -->
<div>我是 iframe</div>
<script>
window.addEventListener("load", () => {
console.log("子文档 load 事件");
});
</script>
复制

主文档加载完成后,开始解析和加载 iframe 内容。结果是子文档的 load 事件先触发,然后触发父文档的 load 事件:

loading 属性

iframe 的子文档会延迟父文档的 load 事件,这是因为 iframe 的加载默认是同步的,我们可以通过 loading 属性设置为异步。

loading 是一个懒加载属性,用于定义在视口之外iframe 元素的加载策略。其主要目的是通过延迟加载不在视口范围内的 iframe,提高页面性能和资源利用效率

loading 属性只对 src 属性有效,对 srcdoc 属性是无效的

它的值可以是:

  • lazy(懒加载)
    表示只有当 iframe 接近或进入视口时才开始加载。就算 iframe 一开始就在视口范围内,它仍然是懒加载的,父文档的 load 事件会先执行,iframe load 事件后执行

  • eager(即时加载)
    默认值,表示 iframe 应立即加载,无论是否在视口范围内。

仍然使用上面的例子,在父文档的 iframe 元素加上 loading 属性:

<iframe src="child.html" loading="lazy"></iframe>
复制

可以看到,父文档的 load 事件先执行了,子文档不再延迟父文档的 load 事件。

使用 loading="lazy" 时,浏览器会推迟 iframe 的网络请求和渲染,直到其即将进入视口。这可能会减少带宽占用,但也可能导致用户在快速滚动时看到加载延迟。所以对于关键内容建议不要懒加载,或者自定义控制加载时机。

sandbox 属性

通过 sandbox 属性可以对嵌入内容施加额外的安全限制,允许开发者逐步放宽某些默认的沙箱限制。它是强化安全的关键机制,用于隔离潜在的不可信内容。

设置 sandbox 属性后,嵌入内容会被视为来自一个不透明源(opaque origin),嵌入内容被隔离,无法共享任何同源信息。可使用 allow-same-origin 解除此限制,使内容被视为来自其实际来源。

它的值可以是(可以组合):

  • allow-same-origin:允许内容与其来源共享相同的安全上下文(即不跨域沙箱化)。否则即使它与宿主页面同源,内容仍会被限制为跨域环境(说人话,就是因为 sandbox 属性会创建一个不透明源,使用该属性可以解除不透明源)。该属性使内容被视为来自其实际的 origin如果没有设置该值,iframe 无法访问 cookie、web storage 等

  • allow-downloads:允许嵌入的内容触发下载操作(例如 <a download>)。默认情况下,沙箱环境会阻止下载。由于通过 a 元素的 download 属性下载文件,要求下载的文件必须与触发下载的页面同源,所以还必须给 iframe 加上 allow-same-origin,让子文档变成其实际的 origin,才能下载成功。

  • allow-forms:允许提交表单。默认情况下,表单提交被禁用。

  • allow-modals:允许使用模态对话框(如 alert()prompt()confirm())。默认情况下,模态对话框被禁用。

  • allow-orientation-lock:允许内容锁定设备的屏幕方向。

  • allow-pointer-lock:允许内容锁定指针(如使用 pointerlock API)。默认情况下,指针锁定被禁用。

  • allow-popups:允许弹出窗口(如 window.open() )。默认情况下,弹出窗口被阻止。

  • allow-popups-to-escape-sandbox:允许弹出的窗口跳过沙箱限制。必须配合 allow-popups 使用。默认情况下,iframe 嵌入内容打开的新窗口,仍会受 sandbox 影响。

  • allow-presentation:允许内容启动演示模式,例如通过 Presentation API

  • allow-scripts:允许脚本执行,但不允许创建新的弹出窗口(除非同时使用 allow-popups)。默认情况下,脚本被禁用。

  • allow-top-navigation:允许 iframe 内容触发顶层导航(即替换宿主页面)例如,window.top.location = "https://baidu.com可生效。默认情况下,顶层导航被禁用。

  • allow-top-navigation-by-user-activation:仅允许通过用户操作(如点击链接或按钮)触发顶层导航。

  • allow-top-navigation-to-custom-protocols:允许嵌入内容导航到自定义协议(如 mailto:tel:)。要小心使用,避免潜在安全风险。

当指定 sandbox 属性但未设置任何值时,所有的限制均启用(完全沙箱化)。需要放宽某些限制,就必须显式添加相应的值

但是大家注意⚠️,滥用放宽限制可能导致安全风险,应在满足最小权限原则的前提下使用

allow-scripts 与 allow-same-origin 同时存在

allow-scriptsallow-same-origin 同时存在时,并且嵌入的页面与包含 iframe 的页面同源,嵌入的页面就可以突破沙盒限制

  1. 嵌入的页面可以通过脚本操作 window.parent.document 或通过 window.frameElement 获取自身的 iframe 元素,直接移除 sandbox 属性。

  1. 一旦 sandbox 属性被移除,嵌入页面重新加载后,沙盒限制将不再生效。

父文档:

<h1>前端创可贴</h1>
<iframe
src="child.html"
sandbox="allow-scripts allow-same-origin">
</iframe>
复制

子文档:

<div>我是 iframe</div>
<script>
(() => {
// 获取窗口嵌入的元素
const iframeElement = window.frameElement;
if (!iframeElement.hasAttribute("sandbox")) {
return;
}
// 移除 iframe 的 sandbox 属性
iframeElement.removeAttribute("sandbox");
// 重新加载页面
window.location.reload();
})();
</script>
复制

iframe 嵌入内容不再受沙盒限制,sandbox 属性被删除了。

sandbox 会影响 iframe 内新打开的 tab

sandbox 属性管的非常宽,它不仅会影响 iframe 文档,甚至还会影响 iframe 内通过 window.open 打开的新窗口。

例如 iframe 打开一个新 tab,新 tab 执行 alert 方法,如果顶层的 iframe 的 sandbox 属性没有设置 allow-modal,新 tab 执行 alert 就会失败。

通过设置 sandbox 属性值为 allow-popups-to-escape-sandbox,可以让新窗口不受 sandbox 影响。

移除 sandbox 属性

sandbox 属性中的限制和权限仅在 iframe 元素的内容导航(即加载新的内容)时生效。

如果 iframe 已经加载了某个页面,动态移除或修改 sandbox 属性并不会改变当前已加载内容的权限,当前页面仍受加载时的 sandbox 限制约束。

要使移除 sandbox 生效,必须重新加载 iframe 内容,例如重新赋值 src即使赋值为原来的值,iframe 也会重新加载)。

// 重新导航 iframe,使修改的 sandbox 属性生效
iframe.removeAttribute('sandbox');
iframe.src = 'xxx';
复制

新加载的内容不再受 sandbox 限制,因为加载时 sandbox 属性已被移除。

什么场景下会出现删除 sandbox 属性的情况呢?比如默认情况下加载内容时启用 sandbox,用以确保内容在加载时受到限制,在经过安全性评估后,可以通过移除 sandbox 属性并重新加载内容,为新加载的页面解除限制。

但是大家注意⚠️,这种动态操作可能导致复杂的安全问题,并使行为难以预测,所以建议大家尽量不要动态操作 sandbox 属性,可能会出现意料之外的安全风险,并且难以维护。

allow 属性

allow 属性用于定义一个 权限策略(Permissions Policy),其主要作用是为 iframe 内嵌内容指定某些 Web 平台特性的可用性,更加精细化地增强安全性和功能控制。

我们先来看看什么是权限策略。

权限策略(Permissions Policy)

与 allow 属性的作用相同,事实上 allow 属性是应用权限策略的方式之一。用于精细化地控制 Web 功能,限制功能是否可用并且限制哪些指定的 origin 可用。

权限策略和内容安全策略(Content Security Policy,CSP)比较像,他们的写法比较相似,只是权限策略不是控制安全行为相关,而是控制一些精细化的 Web 功能,例如定位、摄像头、麦克风等。

权限策略以前被叫做功能策略(Feature Policy),如果大家见到叫做这个名字的 HTTP 响应头,它们的作用是一样的。

权限策略,有两种启用方式:

  • 通过 HTTP 响应头 Permissions-Policy 设置,影响当前文档及其内部所有 iframe 文档。

  • 通过 iframe 元素的 allow 属性设置,只影响当前 iframe 文档。

继承

如果上述两种启用方式同时都设置了,对于当前文档来说只会应用响应头的限制;而对于 iframe 元素来说,会结合两者,使用最大程度的限制,iframe 要使用的 Web 功能必须同时满足 Permissions-Policy 响应头以及 allow 属性的 origin 限制。

同样的,如果父 iframe 和子 iframe 都设置了 allow 属性,子 iframe 也会结合两者,使用最大程度的限制。

如果 Permissions-Policy 响应头或者父 iframe 的 allow 属性禁用了某个功能,所有的子级 iframe 都无法开启这个功能,包括所有后代的 iframe(孙子、重孙子等)。

权限策略(permissions policy)所支持的值,包含 功能名称 允许来源

功能名称

常见的功能有:

  • autoplay:允许媒体自动播放。
  • camera:允许使用摄像头。
  • document-domain:允许设置 document.domain 的值。
  • fullscreen:允许使用全屏 API 进行全屏。
  • geolocation:允许使用定位 API。
  • microphone:允许使用麦克风。
  • picture-in-picture:允许视频以画中画的形式播放。
  • ...

允许来源

指定功能可以应用在哪些 origin,值包含在括号里,用空格隔开。

它的值可以是:

  • *:任意 origin 都可以使用功能。
  • ()(空来源):任意 origin 都禁用使用功能。
  • self:只有同源才可以使用功能。如果嵌入的 iframe 地址与当前文档非同源,则无法使用功能。
  • 'src':只有和当前 iframe 的 src 属性同源,才可以使用功能。该值只能用在 iframe 的 allow 属性,也是其允许来源的默认值,也就是说例如 <iframe allow="geolocation"> 等同于 <iframe allow="geolocation 'src'">
  • "<origin>":只有指定的域名才可以使用功能,可以指定多个域名,用空格隔开。可以使用通配符 *。如果用在 iframe 元素的 allow 属性,则要去掉引号。

例如:

  • *
  • ()
  • (self)
  • (src)
  • (self "https://a.example.com" "https://b.example.com"
  • ("https://*.example.com")

Permissions-Policy 响应头的格式为:Permissions-Policy: <directive>=<allowlist>

用法

介绍完了权限策略,看看如何通过 allow 属性来启用权限策略。

对于 iframe 来说,allow 属性中的功能需要同时满足父文档的限制,所以如果父文档的 HTTP 响应头中指定了功能范围,iframe allow 属性必须是功能范围的子集。

allow 属性值的格式如下:

<iframe allow="权限名称1 'self'; 权限名称2 'none'; 权限名称3 https://example.com"></iframe>
复制

例如给 iframe 设置只有跟当前文档以及指定 origin 同源时才能使用功能:

<iframe
src="https://example.com"
allow="geolocation 'self' https://a.example.com https://b.example.com; fullscreen 'none'"></iframe>
复制

如果当前的 iframe 并没有用到别的 origin,但是含有链接可以跳转到别的 origin,跳转后的页面仍然在 allow 属性的管辖范围内,所以如果不在 allow 属性中指定别的 origin,当跳转后就会出现功能不可用的问题

referrerpolicy 属性

用于控制访问 iframe 资源时的 referrer 请求头。

它的值可以是:

  • no-referrer完全不发送 Referer 请求头。
  • no-referrer-when-downgrade:当目标页面使用 HTTPS 时,发送完整的 Referer;如果从 HTTPS 访问 HTTP,则不发送 Referer。
  • origin:仅发送来源页面的 协议、主机名和端口号,也就是只发送源 origin,不包含路径或查询参数。
  • origin-when-cross-origin:同源请求发送完整的 URL 作为 Referer;跨域请求仅发送源 origin。
  • same-origin:同源请求发送完整的 Referer;跨域请求不发送任何 Referer
  • strict-origin:当协议安全级别一致(如 HTTPS → HTTPS)时,仅发送源 origin。当从 HTTPS 访问 HTTP 时,不发送 Referer
  • strict-origin-when-cross-origin
    • 同源请求:发送完整的 URL。
    • 跨域请求(协议安全级别一致,如 HTTPS → HTTPS):仅发送源 origin。
    • 跨域请求(从 HTTPS 到 HTTP):不发送 Referer
  • unsafe-url:发送完整的 URL。

通信

父文档与子文档有时需要进行通信,例如子文档渲染完成后调用父文档的函数。

父子文档通信有 3 种方式:

  • 同源时,通过 contentWindowwindow.parent 访问对方的 Window 对象。
  • 非同源时,通过 postMessage 方式。
  • 非同源时,通过 postMessage + MessageChannel 方式。

方式一:通过 parent 方式通信。

<!-- 父文档 -->
<h1>前端创可贴</h1>
<iframe src="./child.html" frameborder="0"></iframe>
<script>
window.customData = "你好我是前端创可贴";
</script>
复制
<!-- 子文档 -->
<div>我是 iframe</div>
<script>
console.log("通过 parent 从父文档获取的数据:", parent.customData);
</script>
复制

方式二:通过 postMessage 方式通信。

<!-- 父文档 -->
<h1>前端创可贴</h1>
<button id="btn">发送数据</button>
<iframe id="iframe" src="./child.html" frameborder="0"></iframe>
<script>
btn.addEventListener("click", () => {
iframe.contentWindow.postMessage("你好我是前端创可贴", "*");
});
</script>
复制
<!-- 子文档 -->
<div>我是 iframe</div>
<script>
addEventListener("message", (e) => {
console.log("通过 postMessage 从父文档获取的数据:", e.data);
});
</script>
复制

方式三:通过 postMessage + MessageChannel 方式通信。

<!-- 父文档 -->
<h1>前端创可贴</h1>
<button id="btn">发送数据</button>
<iframe id="iframe" src="./child.html" frameborder="0"></iframe>
<script>
const p = new MessageChannel();
btn.addEventListener("click", () => {
iframe.contentWindow.postMessage("", "*", [p.port2]);
setTimeout(() => {
p.port1.postMessage("你好我是前端创可贴");
});
});
</script>
复制
<!-- 子文档 -->
<div>我是 iframe</div>
<script>
addEventListener("message", (e) => {
const port = e.ports[0];
port.onmessage = (e) => {
console.log("通过 messageChannel 从父文档获取的数据:", e.data);
};
});
</script>
复制

iframe 内的页面跳转

iframe 里的文档可以进行页面的跳转,会在顶层文档中留下历史记录,也就是可以点击浏览器的后退和前进iframe 里的页面跳转(包括点击浏览器的前进后退按钮)不会影响顶层页面的 URL,也不会影响 iframe 之外的元素

大家可以看到,在 iframe 里产生页面跳转,并不会影响外层元素以及 url。如果 iframe 页面跳转以后再刷新页面:

可以看到,iframe 内的状态丢失了,在 url 上也没有任何改变,这也就是为什么大家不用 iframe 实现微前端的原因之一

其实也可以实现让页面 url 一起变化,但是需要一些额外编码,并且耦合性有点高。

一起来简单实现一下,当 iframe 内进行页面跳转时,影响顶层文档的 url。

拦截子文档内的所有 a 元素跳转,点击 a 元素会向父文档通过 postMessage 发送 a 元素要跳转的路径,父文档通过 message 事件获取到路径后通过 history.pushState 修改 url。并且页面刷新时,父文档将当前 url 中的路径同样通过 postMessage 发送给子文档,子文档获取到后修改子文档的 href,展示跳转后的页面。

parent 页面:

<body>
<h1>前端创可贴 parent</h1>
<iframe
id="iframe"
src="child.html"
frameborder="0"
></iframe>
</body>
<script>
window.addEventListener("message", (event) => {
if (event.origin !== "http://127.0.0.1:5500") return;
// 获取 iframe 的路径
const iframePath = event.data.path;
// 更新父页面的 URL(不重新加载页面)
history.pushState(null, "", iframePath);
});
// 父页面加载时,解析 URL 并初始化 iframe 状态
window.addEventListener("load", () => {
const currentPath = window.location.pathname;
// 初次加载时不发送路径给子文档
if (currentPath === "/turbo/apps/iframe/parent.html") {
return;
}
// 将当前父页面 URL 的路径传递给 iframe
iframe.contentWindow.postMessage({ path: currentPath }, "*");
});
</script>
复制

child 页面:

<body>
<h1>child</h1>
<a href="./child2.html">跳转</a>
</body>
<script>
const updateParentUrl = (path) => {
window.parent.postMessage({ path }, "*"); // 向父页面发送路径信息
};
// 模拟内容切换
const links = document.querySelectorAll("a");
links.forEach((link) => {
link.addEventListener("click", (event) => {
event.preventDefault(); // 阻止默认跳转
const newPath = event.target.getAttribute("href");
// 修改当前子文档内容
location.href = newPath;
// 通知父页面更新 URL
updateParentUrl(newPath);
});
});
// 监听来自父页面的消息,更新 iframe 状态
window.addEventListener("message", (event) => {
if (event.origin !== "http://127.0.0.1:5500") return;
const { path } = event.data;
location.href = path;
});
</script>
复制

通过这种方式可以实现 url 的同步,不丢失 iframe 状态。但是还存在很多问题,例如:

  • 耦合性很高,子文档无法脱离父文档单独运行,违背了微前端独立部署的特性(直接宣判死刑);

  • 我们是通过父文档的 history.pushState 实现的 url 变化,由于 history API 的特性,点击浏览器的前进后退按钮,页面是不会刷新的,我们还需要监听 popstate 事件继续做额外的工作。

  • 我们通过父文档的 pushState 增加了一个历史记录,而子文档修改了 location.href 也会增加一个历史记录,导致一次链接跳转出现了 2 个历史记录。如果使用 replaceState 代替,就会出现页面返回时无法再复原原来的 url。

  • 我们确实修改了 url,对于单页面项目来说,刷新页面不会有问题,一定会由父文档将路径传给子文档;而如果是多页面项目,此时 url 是一个子文档中的真实 url,刷新后只会展示子文档而丢失了父文档的展示。
  • ...

可以看到,问题还有很多,所以 iframe 实现微前端是有很多问题的,这里我们只介绍了 url 不同步的问题,限于篇幅已经很长,以后有机会再跟大家细聊 iframe 实现微前端的优缺点。

结束语

这一章我们学习了 iframe 的相关内容,掌握了 iframe 的用法,包括 src、srcdoc、loading 属性、sandbox 属性、allow 属性等,全方面的学习了如何更好的使用和控制 iframe,保障嵌入的内容不会影响外层内容的安全。

最后还扩充了一下 iframe 内部跳转链接,介绍了为何业界普遍不采用 iframe 作为微前端解决方案的原因之一,碍于篇幅原因没有再介绍 iframe 实现微前端的优缺点,以后有时间再跟大家细说。

那么这一章的介绍就结束了,咱们下一章再见啦。


欢迎关注我的公众号,前端创可贴。
 

转载请注明出处或者链接地址:https://www.qianduange.cn//article/23172.html
标签
评论
还可以输入200
共0条数据,当前/页
会员中心 联系我 留言建议 回顶部
复制成功!