html 内嵌标签iframe

特点

  • 默认可以加载不同域的网页,但通信存在跨域限制
  • 不允许网页被 iframe 跨域加载

    • 设置响应头 & meta(即csp):X-Frame-Options
      • SAMEORIGIN:表示网页只允许在相同域名的 iframe 中显示
      • DENY:表示网页不允许在任何 iframe 中显示
      • ALLOW-FROM uri:表示网页允许在指定的 uri 中显示
    • 设置响应头 & meta(即csp):Content-Security-Policy
      • Content-Security-Policy: frame-ancestors ‘self’ https://allowed-site.com
        • 只允许在同一源站点的 iframe 中加载网页和其他指定允许的站点
// csp 方式
<meta http-equiv="Content-Security-Policy" content="frame-ancestors 'self'">
  • https 的网页不可以嵌套 http 的网页
  • 同源情况下在主页面中可以访问 cookie、localStorage 但无法访问 iframe 中页面的 sessionStorage
    • 如果 iframe 中页面的 cookie 设置了 HttpOnly 属性,那么主应用无法获取
    • iframe 中设置的 cookie 会覆盖主应用的

属性

  • allow:允许使用的权限策略,详情
  • height、width
  • name
    • 用于定位嵌入的浏览上下文的名称
    • window.open() 方法的 windowName 参数值。
    • <a> 标签与 <form> 标签的 target 属性值
    • <input> 标签和 <button> 标签的 formtarget 属性值
<a href="http://www.jd.com" target="_jd">京东</a>
<iframe src="" width="100%" height="400px" name="_jd"></iframe>
  • referrerpolicy:在获取 iframe 资源时如何发送 referrer 首部,详情
  • sandbox:在 iframe 框架中的内容启用一些额外的限制条件,比如:allow-scripts 允许嵌入的浏览上下文运行脚本,详情
  • src:同源网站
  • srcdoc:该属性是一段 HTML 代码,这些代码会被渲染到 iframe 中。如果浏览器不支持 srcdoc 属性,则会渲染 src 属性表示的内容。

api

  • window.frames:获取所有 iframe (类数组)
  • iframe DOM对象.contentWindow:获取内联框架的 window 对象
    • window.frames[ 0 ] 与 document.getElementsByTagName( “iframe” )[ 0 ].contentWindow 是相同的
  • iframe DOM对象.contentDocument:获取 <iframe> 内部的 document 元素
    • 等同于 contentWindow.document
  • window.parent:引用父窗口对象
  • window.top:获取顶级窗口对象
  • iframe.onload 生命周期,初始直接访问的文档和加载完成的文档并不是一个
 let oldDoc = iframe.contentDocument;
 
 iframe.onload = function() {
     let newDoc = iframe.contentDocument;
     // 加载的文档与初始的文档不同!
     alert(oldDoc == newDoc); // false
 };

跨域通信

  • 发送消息:接受消息 window对象.postMessage(message, targetOrigin, [transfer]);
    • targetOrigin:“*”(表示无限制)或者一个 URI。在发送消息的时候,如果目标窗口的协议、主机地址或端口这三者的任意一项不匹配 targetOrigin 提供的值,那么消息就不会被发送;只有三者完全匹配,消息才会被发送。
iframe.contentWindow.postMessage(message, targetOrigin, [transfer]);
  • 接收消息
    • data:信息。
    • origin:调用 postMessage 时消息发送方窗口的 origin . 这个字符串由 协议、“😕/“、域名、“ : 端口号”拼接而成。
    • source:对发送消息的窗口对象的引用; 可以使用此来在具有不同 origin 的两个窗口之间建立双向通信
window.addEventListener("message", receiveMessage, false);

缺点

  • 页面样式风格不统一,同步样式存在问题
  • 阻塞顶层页面的 onload 事件
    • 内嵌页面加载完毕之后,主页面才加载完毕。
  • 与主页面共享连接池
    • 顶层页面和内层页面共享连接池,在 chrome 下同时只能发送 6 个 http 请求,iframe 的嵌入会影响主页面的资源加载。
  • 允许嵌入跨域网页存在点击劫持的风险
    • 比如将嵌入一个银行钓鱼网站,窃取用户的输入信息
  • 主应用的后退按钮无法回退 iframe 中的页面 ,也就是 url 不同步
  • 不利于SEO,搜索引擎的爬虫无法解读iframe的页面。

解决方案

url 不同步

  • 通过 js 操作iframe 路由栈
  • iframe使用相对路径
```javascript
<iframe src="comments.html"></iframe>

// 此时,iframe 的完整 URL:https://www.example.com/blog/posts/comments.html
// 主页面 URL 变更为:https://www.example.com/blog/posts/new
// iframe 的 URL 变更为:https://www.example.com/blog/posts/new/comments.html

跨域通信

  • postMessage
  • document.domain
    • iframe为子域时,在父页面和子页面中都设置 document.domain 属性为相同的父域名。例如,在 “www.example.com” 的页面和 “blog.example.com” 的页面中都设置 document.domain = “example.com”
// 在主应用中定义变量
document.domain = "example.com";
var myVar = "Hello, world!";

// 在 iframe 中的页面中访问变量
document.domain = "example.com";
console.log(window.parent.myVar); /

ui 不同步

  • 通过全屏iframe,将浏览器窗口全部交给子应用,代表框架:擎天
    • iframe可以通过 allow 属性来允许全屏

iframe 重复加载

  • 利用 JavaScript 动态加载 iframe: 仅在需要时才通过 JavaScript 创建和插入 iframe 标签,避免页面初次加载时不必要的 iframe 加载。
function loadIframe() {
  const iframe = document.createElement("iframe");
  iframe.src = "https://example.com";
  document.body.appendChild(iframe);
}
  • 异步加载 iframe: 使用 loading=“lazy” 属性可以让浏览器延迟加载不在当前视口内的 iframe
<iframe src="https://example.com" loading="lazy"></iframe>
  • 使用懒加载策略: 对于位于视口外的 iframe,需要在其进入视口时再进行加载
function handleIntersection(entries) {
  entries.forEach((entry) => {
    if (entry.isIntersecting) {
      const iframe = entry.target;
      iframe.src = iframe.dataset.src;
      observer.unobserve(iframe); // 取消观察
    }
  });
}

const observer = new IntersectionObserver(handleIntersection);
const iframes = document.querySelectorAll("iframe");
iframes.forEach((iframe) => observer.observe(iframe));
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值