iframe 之间传值 、iframe与外部之间传值及iframe跨域的问题解决思路(提供完整例子)

需要、假设

假设 父组件下有两个同级的iframe1子组件与iframe2子组件;
需求是 父组件可以与iframe之间传值,iframe1iframe2之间也可以相互传值;

不跨域 思路:

1、不跨域情况下,父组件向iframe子组件传值;
方法一、子组件定义函数fn, 父组件 通过iframecontentWindow获取到子组件fn,并通过fn传值到iframe子组件;
方法二、父组件 通过向iframecontentWindow添加属性,子组件需要时通过Window[属性名]获取父元素传递的数据;
方法三、子组件使用parent可以获取到父组件的window;
2、不跨域情况下,iframe子组件向父组件传值;
方法一、父元素定义函数getChild并通过向iframecontentWindow添加getChild方法,子组件通过Window.getChild();传值给父组件;
3、iframe1iframe2之间也可以相互传值;
方法一、通过子组件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>

效果

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43245095/article/details/110224343