全国免费咨询:

13245491521

VR图标白色 VR图标黑色
X

中高端软件定制开发服务商

与我们取得联系

13245491521     13245491521

2024-11-05_用iframe必定遇到过这六种“坑”之一(以vue为示例)

您的位置:首页 >> 新闻 >> 行业资讯

用iframe必定遇到过这六种“坑”之一(以vue为示例) 点击关注公众号,“技术干货”及时达! 前言如果你是做web前端,那么不可避免早晚都会用到iframe的。其实博主很久前用过,但最近又要有项目用了,由于年代久远对iframe的注意事项都有点忘记了,然后想着总结一下比较需要注意的几个重点事项,除了便于高效工作还能分享给有需要用到iframe的小伙伴。 iframe基于父窗口大小自适应宽高「简述:」这是iframe最常见的需求了,有时候我们用iframe嵌入一个页面时,不想固定宽高想跟随父系统屏幕大小动态变化,从而大大提高适配性。 「实现思路:」iframe标签绑定:style来动态设置宽高,监听父窗口宽高变化时动态获取并且绑定到:style,但监听变化需要考虑到初始化和窗口缩放的情况,并且记得移除事件监听器防止内存泄漏。 「完整实现代码如下所示」 template div class="box" @resize="iframeResize" iframe :src="iframeSrc" :style="{ width: '100%', height: frameHeight + 'px' }" ref="myRef"/iframe /div /template script setup import { onMounted, onUnmounted, ref, watchEffect } from 'vue'; const myRef = ref(null); const iframeSrc = 'https:******.com'; const frameHeight = ref(0); // 调整iframe的高度的方法 function initHeight() { if (myRef.value) { frameHeight.value = window.innerHeight; } } // 窗口大小变化触发 function iframeResize() { initHeight(); } // 移除事件监听器, 防止内存泄漏 onUnmounted(() = { window.removeEventListener('resize', iframeResize); }); // 在组件挂载时先获取一次iframe高度 onMounted(() = { initHeight(); window.addEventListener('resize', iframeResize); }); // 时刻监听变化,防止iframeRef没有赋值 watchEffect(() = { if (myRef.value) { initHeight(); } }); /script style scoped .box { position: relative; width: 100%; height: 100vh; } /style iframe基于内容动态宽高「简述:」例如我们业务需求嵌入的是一个表格而不是一个页面,并且表格高度并不确定时我们不能固定iframe的高度,否则只有一条内容或者没有内容的时候会不好看,这里要根据内容的数量去决定ifram嵌入窗口的高度。 「实现思路:」思路是子窗口通信告诉父窗口具体高度,然后父窗口再动态设置高度即可。具体实现是子窗口利用window.postMessage来发送具体高度,然后父窗口用window.addEventListener('message', 方法)接收内容,从而根据接收到的内容动态调整iframe的高度。 「子窗口(被嵌入页面)代码」 script setup window.onload = function() { let height = '想要告诉父窗口的高度' if (window.parent && window.parent.postMessage) { window.parent.postMessage({height: height}, '*'); } }; /script 「父窗口代码」 template div iframe :src="iframeSrc" ref="myRef"/iframe /div /template script setup import { onMounted, ref } from 'vue'; const iframeSrc = 'https:******.com'; const myRef = ref(null); onMounted(() = { window.addEventListener('message', iframeMessage); }); const iframeMessage = (event) = { // 验证消息来源,确保安全性 if (event.origin !== 'https:******.com') return; const newHeight = event.data.height; if (newHeight && myRef.value) { myRef.value.style.height = `${newHeight}px`; } }; /script 「注意:」 if (event.origin !== 'https:******.com') return这行代码记得加上。 iframe嵌入页面免登录处理这个小弟有单独写过相关详细文章,并且分析了几种情况的处理方式,移步:iframe嵌入页面实现免登录 http无法嵌入https「简述:」例如开发环境是HTTP,嵌入的环境是生产环境的HTTPS,这时就会发现这个问题了。其实是现代浏览器的安全机制,会认为是跨域不同源而禁止。因为HTTP协议传输的数据未加密的会有安全风险。 「解决思路:」网上五花八门的方法,但其实真正靠谱的就两种,(1)将HTTP转换成HTTPS(2)使用代理服务。 方法一:将HTTP转换成HTTPS(推荐)1、获取 SSL 证书并安装方法不止一种,这里就细说啦。 2、配置服务器(这里以nginx为例)下面我把核心部分解释放在注释说明,这是简单版本用于说明HTTP转HTTPS,如果真的上生产其实还有不少其它配置。 server { listen 80; // 监听http默认的80端口 return 301 https://$host$request_uri; // 把所有http永久重定向到https server_name ****.com www.****.com; // 指定域名,这里视真实情况而定 } server { listen 443 ssl; // 监听https默认的443端口。 server_name ****.com www.****.com; // 指定域名,这里视真实情况而定 // 指定 SSL 证书文件路径。 ssl_certificate /etc/lets/live/****.com/fullchain.pem; // 指定 SSL 私钥文件路径 ssl_certificate_key /etc/lets/live/****.com/privkey.pem; location / { index index.html index.htm; root /var/w/html; } } 方法二:使用代理服务用nodejs搭建个简单的代理服务器(这里是用nodejs举例,真实业务场景可能是后端那边搞) 要先安装对应的依赖,例如 npm init -y npm install express http-proxy 然后再配置对应的代理服务器,主要核心是下面四个模块 ?express:作用是构建Web应用。http:作用是处理HTTP请求。https:作用是处理HTTPS请求。httpProxy:作用是创建代理服务器。?const express = require('express'); const fs = require('fs'); const https = require('https'); const http = require('http'); const httpProxy = require('http-proxy'); const app = express(); const proxy = httpProxy.createProxyServer(); const port = 3000; // 读取对应的SSL证书文件 const options = { key: fs.readFileSync('/etc/lets/live/proxy.****.com/privkey.pem'), cert: fs.readFileSync('/etc/lets/live/proxy.****.com/fullchain.pem') }; // 设置路由信息 app.all('/proxy/*', (req, res) = { const targetUrl = `http://${req.params[0]}`; proxy.web(req, res, { target: targetUrl }, (error) = { res.status(500).send('Proxy request failed'); }); }); // 创建HTTPS服务器 const server = https.createServer(options, app); // 启动代理服务器 server.listen(port, () = { console.log(`HTTPS`); }); 跨域问题「简述:」iframe页面的跨域问题是因为涉及到浏览器的安全策略,即同源策略。同源策略限制了一个网页脚本不能读写不同源页面的DOM与Cookie之类的信息。即如果iframe中的内容与包含它的页面不在同一个源上,那么这两个页面之间会受到跨域限制。 「解决思路:」 1、使用 window.postMessage 实现跨域通信父页面代码:主要用window.addEventListener监听消息用postMessage发送消息。 「注意」:@load加载完成后再监听和window.removeEventListener取消监听这两个细节。 template div iframe :src="iframeSrc" ref="iframeRef" @load="onIframeLoad" style="width: 100%; height: 400px;"/iframe button @click="sendMessage"发送消息/button /div /template script setup import { ref, onMounted } from 'vue'; onMounted(() = { window.addEventListener('message', handleMessage); // 在组件卸载时移除事件监听器 return () = { window.removeEventListener('message', handleMessage); }; }); const iframeSrc = 'http://***.com'; const iframeRef = ref(null); // 当 iframe 加载完成后,再设置监听器 const onIframeLoad = () = { window.addEventListener('message', handleMessage); }; const sendMessage = () = { const iframe = iframeRef.value; if (iframe.contentWindow) { iframe.contentWindow.postMessage('Hello!', 'http://***.com'); } }; const handleMessage = (event) = { // 确保来自想要的源才处理消息 if (event.origin !== 'http://***.com') return; console.log( event.data); }; /script 子页面代码:和父页面一样,用window.addEventListener监听消息用postMessage发送消息。 template div button @click="sendMessage"发送消息到父页面/button /div /template script setup import { ref, onMounted } from 'vue'; onMounted(() = { window.addEventListener('message', handleMessage); // 在组件卸载时移除事件监听器 return () = { window.removeEventListener('message', handleMessage); }; }); const sendMessage = () = { const parentWindow = window.parent; if (parentWindow) { parentWindow.postMessage('Hello!', 'http://****.com'); } }; const handleMessage = (event) = { if (event.origin !== 'http://****.com') return; console.log(event.data); }; /script 2、使用 document.domaindocument.domain用于解决二级域名之间跨域问题的方法,例如:a.tty.com和b.tty.com,它们都属于同一个顶级域名tty.com,这时就适合用document.domain来让这两个页面能够相互访问。用法相当于简单,就是分别设置两个页面的document.domain。 核心代码在第10与19行。 template div iframe :src="iframeSrc" @load="onIframeLoad" ref="iframeRef"/iframe /div /template script setup import { ref } from 'vue'; document.domain = 'tty.com'; // 设置顶级域名 const iframeRef = ref(null); const iframeSrc = 'http://b.tty.com'; const onIframeLoad = () = { const iframe = iframeRef.value; if (iframe.contentWindow) { // 设置iframe的 document.domain iframe.contentWindow.document.domain = 'tty.com'; } }; /script 3、使用 CORS这里主要是后端的配置了,通过调整服务器响应头中的Access-Control-Allow-Origin来控制哪些源是可以安全访问资源。 以为nginx为例,*设置为所有。 http { server { listen 80; server_name yourdomain.com; # 替换为你的域名 # 代理 iframe 请求并添加 CORS 头部 location /iframe-proxy/ { # 添加CORS头部 add_header Access-Control-Allow-Origin *; # 其他配置... } } } 4、nginx配置代理算是常见解决方案了,思路是通过Nginx反向代理,将请求重定向到想要请求的目标服务器。 核心就是第10行代码,具体可以特意去看看nginx。 http { server { listen 80; server_name yourdomain.com; # 替换为你的域名 # 代理 iframe 请求并添加 CORS 头部 location /iframe-proxy/ { # 将请求代理到目标 proxy_pass http://tty.com/; # 其他配置... } } } iframe嵌入后报拒绝连接请求不知道你用iframe有没有见过这个页面,这通常是目标页面设置了X-Frame-Options响应头来限制内容被嵌入到其他站点的iframe中。这个可以找后端看看X-Frame-Options。 小结都是把遇到的场景总结了一下,感觉都是比较常见的情况。 如果大佬们有什么iframe的“坑”也可以分享一下我同步学习一下,还有那里写的不好也可以指出更正鸭 点击关注公众号,“技术干货”及时达!

上一篇:2025-05-13_「一录同行 · 厦门站」5月17日正式开场!30+品牌器材 × 4场讲座 × 全天实操,免费开放! 下一篇:2021-02-24_中山大学发布无偏视觉问答数据集KRVQA,论文登上顶刊TNNLS

TAG标签:

15
网站开发网络凭借多年的网站建设经验,坚持以“帮助中小企业实现网络营销化”为宗旨,累计为4000多家客户提供品质建站服务,得到了客户的一致好评。如果您有网站建设网站改版域名注册主机空间手机网站建设网站备案等方面的需求...
请立即点击咨询我们或拨打咨询热线:13245491521 13245491521 ,我们会详细为你一一解答你心中的疑难。
项目经理在线

相关阅读 更多>>

猜您喜欢更多>>

我们已经准备好了,你呢?
2022我们与您携手共赢,为您的企业营销保驾护航!

不达标就退款

高性价比建站

免费网站代备案

1对1原创设计服务

7×24小时售后支持

 

全国免费咨询:

13245491521

业务咨询:13245491521 / 13245491521

节假值班:13245491521()

联系地址:

Copyright © 2019-2025      ICP备案:沪ICP备19027192号-6 法律顾问:律师XXX支持

在线
客服

技术在线服务时间:9:00-20:00

在网站开发,您对接的直接是技术员,而非客服传话!

电话
咨询

13245491521
7*24小时客服热线

13245491521
项目经理手机

微信
咨询

加微信获取报价