iframe 之间传值 、iframe与外部之间传值及iframe跨域的问题解决思路(提供完整例子)
思路假设 父组件下有两个同级的iframe1子组件与iframe2子组件;需求是 父组件可以与iframe之间传值,iframe1与iframe2之间也可以相互传值;不跨域 思路:1、不跨域情况下,父组件向iframe子组件传值;方法一、子组件定义函数fn, 父组件 通过iframe的contentWindow获取到子组件fn,并通过fn传值到iframe子组件;方法二、父组件 通过向iframe
需要、假设
假设 父组件下有两个同级的iframe1
子组件与iframe2
子组件;
需求是 父组件可以与iframe
之间传值,iframe1
与iframe2
之间也可以相互传值;
不跨域 思路:
1、不跨域情况下,父组件向iframe
子组件传值;
方法一、子组件定义函数fn, 父组件 通过iframe
的contentWindow
获取到子组件fn,并通过fn传值到iframe
子组件;
方法二、父组件 通过向iframe
的contentWindow
添加属性,子组件需要时通过Window[属性名]获取父元素传递的数据;
方法三、子组件使用parent
可以获取到父组件的window
;
2、不跨域情况下,iframe
子组件向父组件传值;
方法一、父元素定义函数getChild
并通过向iframe
的contentWindow
添加getChild
方法,子组件通过Window.getChild();
传值给父组件;
3、iframe1
与iframe2
之间也可以相互传值;
方法一、通过子组件iframe1
向父组件传值,再通过父组件向子组件iframe2
传值可达到目的;
注意
:模拟时 需要开启服务器,否则会出现跨域问题!
不跨域例子
父组件 index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<iframe id="iframe1" src="./iframe1.html" width="" height="" frameborder="0" scrolling="no"></iframe>
<iframe id="iframe2" src="./iframe2.html" width="" height="" frameborder="0" scrolling="no"></iframe>
<script type="text/javascript">
let iframe1 = document.getElementById('iframe1');
let iframe2 = document.getElementById('iframe2');
let fatherData = '父元素数据';
window.fatherData = fatherData;
window.onload = () => {
iframe1.contentWindow.getData('父元素window.onload后传入到iframe1 的数据');
iframe1.contentWindow.fatherData = fatherData;
iframe1.contentWindow.getChild = getChild;
iframe1.contentWindow.getIframe2 = getIframe2;
}
function getChild(data) {
console.log('获取到子组件数据', data);
}
function getIframe2(data) {
iframe2.contentWindow.setIframe2(data);
}
</script>
</body>
</html>
子组件 iframe1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>iframe1</title>
</head>
<body>
<div id="">
iframe1
<button type="button" id="btn">获取父组件数据</button>
<button type="button" id="btn1">传值给父组件</button>
<button type="button" id="btn2">传值给ifrme2</button>
</div>
<script type="text/javascript">
let demo1Data = '';
function getData(data) {
demo1Data = data;
console.log('demo1Data', demo1Data);
console.log(parent.fatherData);
}
let btn = document.getElementById('btn');
btn.onclick = () => {
console.log(window.fatherData);
}
let btn1 = document.getElementById('btn1');
btn1.onclick = () => {
window.getChild('hhh');
}
let btn2 = document.getElementById('btn2');
btn2.onclick = () => {
window.getIframe2('ifrme1的数据');
}
// // 这里设置定时获取 是因为 子元素先加载完成 父元素才赋值getFatherData方法;
// let timer = setInterval(() => {
// if (window.getFatherData) {
// console.log(window.getFatherData());
// clearInterval(timer);
// }
// }, 100)
</script>
</body>
</html>
子组件 iframe2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>iframe2</title>
</head>
<body>
<div>
iframe2
</div>
<script type="text/javascript">
function setIframe2(data) {
console.log(data);
}
</script>
</body>
</html>
启动服务器 serve.js
var express =require('express');
var app = require('express')(),server =require('http').createServer(app);
server.listen(8888);
app.use(express.static("./"));
app.get('/',function(req,res){
res.sendFile(__dirname + '/index.html');
});
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:8888/');
启动服务器前 先用node 安装 express
插件;
启动服务器
node serve.js
结果如图
跨域 思路:
1、跨域时通过创建代理页面
的方式,子组件可以操作父组件方法,但使用范围有限;
2、利用location.hash
,父组件给子组件iframe
标签的src
属性链接后面添加#
,子组件通过location.hash
获取父组件数据,从而达到父组件操作子组件,如<iframe id="iframe1" src="http://127.0.0.1:5555/iframe1.html#mas=111" width="" height="" frameborder="0" scrolling="no"></iframe>
3、使用postMessage
实现跨域通信
postMessage方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递。
语法:
otherWindow.postMessage(message, targetOrigin, [transfer]);
otherWindow
:其他窗口的引用,如 iframe的contentWindow、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。
message
:将要发送到其他window的数据。
targetOrigin
:指定那些窗口能接收到消息事件,其值可以是字符串 “*” 表示无限制,或者是一个URI。
transfer
:是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送方将不再保留所有权。
postMessage
方法被调用时,会在所有页面脚本执行完毕之后像目标窗口派发一个 MessageEvent 消息,该MessageEvent
消息有四个属性需要注意:
type
:表示该message的类型
data
:为 postMessage 的第一个参数
origin
:表示调用postMessage方法窗口的源
source
:记录调用postMessage方法的窗口对象
1,2 例子
父组件father下的index.html,serve.js
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<iframe id="iframe1" src="http://127.0.0.1:5555/iframe1.html#mas=111" width="" height="" frameborder="0" scrolling="no"></iframe>
<script type="text/javascript">
let iframe1 = document.getElementById('iframe1');
let fatherData = '父元素数据';
function getFatherData() {
console.log('跨域子组件操作父组件', fatherData);
}
</script>
</body>
</html>
serve.js
var express =require('express');
var app = require('express')(),server =require('http').createServer(app);
server.listen(7777);
app.use(express.static("./"));
app.get('/',function(req,res){
res.sendFile(__dirname + '/iframe1.html');
});
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:7777/');
子组件child下的iframe1.html,serve.js
iframe1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>iframe1</title>
</head>
<body>
<div id="">
iframe1
<!-- <iframe id="iframe1" src="http://127.0.0.1:5555/proxyIframe1.html" width="" height="" frameborder="0" scrolling="no"></iframe> -->
<button type="button" id="btn">操作父元素方法 跨域</button>
</div>
<script type="text/javascript">
console.log('location.hash', location.hash);
let btn = document.getElementById('btn');
btn.onclick = () => {
if (!document.getElementById('proxy')) {
let iframe = document.createElement('iframe');
iframe.setAttribute('style', 'display: none;')
iframe.setAttribute('JSON', '跨域数据');
iframe.setAttribute('src', 'http://127.0.0.1:7777/proxy.html')
document.body.appendChild(iframe);
} else {
document.getElementById('proxy').src = 'http://127.0.0.1:7777/proxy.html';
}
// console.log(parent);
// console.log('window.name', window.name);
}
</script>
</body>
</html>
serve.js
var express =require('express');
var app = require('express')(),server =require('http').createServer(app);
server.listen(5555);
app.use(express.static("./"));
app.get('/',function(req,res){
res.sendFile(__dirname + '/index.html');
});
// 终端打印如下信息
console.log('Server running at http://127.0.0.1:5555/');
效果
3.使用postMessage
实现跨域通信 例子
模拟跨域的serve.js与1、2一样;
父组件father下的index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<iframe id="iframe1" src="http://127.0.0.1:5555/iframe1.html" width="" height="" frameborder="0" scrolling="no"></iframe>
<button type="button" id="btn">给子组件传值</button>
<script type="text/javascript">
let iframe1 = document.getElementById('iframe1');
let btn = document.getElementById('btn');
btn.onclick = () => {
iframe1.contentWindow.postMessage("父组件给子组件的数据",
"http://127.0.0.1:5555/iframe1.html")
}
window.addEventListener('message', function(event) {
console.log('event', event);
}, false);
</script>
</body>
</html>
子组件child下的iframe1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>iframe1</title>
</head>
<body>
<div id="">
iframe1
<button type="button" id="btn">给父组件传值</button>
</div>
<script type="text/javascript">
let btn = document.getElementById('btn');
btn.onclick = () => {
top.postMessage("子组件给父组件的数据", 'http://127.0.0.1:7777/index.html')
}
window.addEventListener('message', function(event) {
console.log('event', event);
}, false);
</script>
</body>
</html>
效果
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)