添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
刚毅的眼镜  ·  Surf Club Rewards - ...·  1 月前    · 
很酷的柑橘  ·  中传要闻·  2 月前    · 
神勇威武的长颈鹿  ·  最高人民法院 ...·  10 月前    · 
坚强的眼镜  ·  TypeError:“datetime.da ...·  10 月前    · 

postMessage iframe跨域解决高度自适应

今天学习一个新的window方法:window. postMessage window.postMessage() 方法可以安全地实现跨源通信。postMessage是html5引入的API,postMessage()方法允许来自不同源的脚本采用异步方式进行有效的通信,可以实现跨文本文档,多窗口, 跨域 消息传递.多用于窗口间数据通信,这也使它成为 跨域 通信的一种有效的解决方案.

之前的一篇 iframe 高度 自适应 的文章想必很多人看过,在同源中,处理比较方便,但是对于不同源的 iframe 处理起来就比较麻烦,需要用到代理页面。而postMessage则直接两个页面交流。

属性详解

postMessage

otherWindow.postMessage(message, targetOrigin, [transfer])

otherWindow
窗口的一个引用,比如iframe的contentWindow属性,执行window.open返回的窗口对象,或者是命名过的或数值索引的window.frames.
message
要发送到其他窗口的数据,它将会被[!结构化克隆算法]( developer.mozilla.org/e )序列化.这意味着你可以不受什么限制的将数据对象安全的传送给目标窗口而无需自己序列化.
targetOrigin
通过窗口的origin属性来指定哪些窗口能接收到消息事件,指定后只有对应origin下的窗口才可以接收到消息,设置为通配符"*"表示可以发送到任何窗口,但通常处于安全性考虑不建议这么做.如果想要发送到与当前窗口同源的窗口,可设置为"/"
transfer | 可选属性
是一串和message同时传递的**Transferable**对象,这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权.

Message事件

window.addEventListener("message", receiveMessage, false) ;
function receiveMessage(event) {
var origin= event.origin;
console.log(event);
}

data 包含任意字符串数据,由原始脚本发送
origin 一个字符串,包含原始文档的方案、域名以及端口(如: domain.example:80 )
lastEventId 一个字符串,包含了当前的消息事件的唯一标识符。
source 原始文件的窗口的引用。更确切地说,它是一个WindowProxy对象。
ports 一个数组,包含任何MessagePort对象发送消息。

常用实例

1.父页面接收子页面内容,这是最常用的,比如iframe自适应、模态弹窗

<body>
<h1>父窗口</h1>
<iframe id="childIframe" src="http://www.wpbars.com/files/childMessage.html"></iframe>
<div id="content"></div>
<script>
	window.addEventListener("message", function( event ) {
         // 把子窗口发送过来的数据显示在父窗口中
       document.getElementById("content").innerHTML=event.data;
     }, false );
</script>
</body>
	<h1>子窗口</h1>
	<script>
		top.postMessage('子窗口发出的内容','*');
	</script>
</body>

演示

2.父页面传送数据给子页面

<body>
<h1>父窗口HTML代码</h1>
<iframe id="childIframe" src="http://www.wpbars.com/files/childMessage3.html"></iframe>
<script>
	var iframe = document.getElementById('childIframe');
	iframe.onload = function(){
		iframe.contentWindow.postMessage('父页面发出的内容','*');
</script>
</body>
	<h1>子窗口</h1>
	<div id="content"></div>
	<script>
		window.addEventListener("message", function( event ) {
         // 把子窗口发送过来的数据显示在父窗口中
       document.getElementById("content").innerHTML=event.data;
     }, false );
	</script>
</body>

演示

安全验证

使用message接收数据时,几乎包含了所有应该有的信息。甚至data中可以包含object,出于安全考虑可以域的校验,数据规则的校验安全校验,如下代码

function getMessge(callback){
	window.addEventListener('message', function (event) {
		//校验函数是否合法
		var checkMessage = function () {
			// 只获取需要的域,并非所有都可以跨域
			if (event.origin != "need domain") {
				return false;
			var message = event.data;
			// 传输数据类型校验
			if (typeof(message) !== 'object') {
				return false;
			// message 的rule中包含xxx则为xxx需要字段。
			return message.rule === "xxx";
		if (checkMessage()) {
			// 通过校验进行相关操作
			callback && callback(event);
}

iframe高度自适应

<body>
<h1>父页面</h1>
<iframe src="http://www.wpbars.com/files/childMessage.html" id='myframe' name="myframe" allowTransparency="true" scrolling="no" width="100%" height="100%" frameborder="0"></iframe>
<script>
var p = document.getElementById('myframe');
	window.postMessage && (window.attachEvent ? window.attachEvent("onmessage",
		function(a) {
			if (0 === parseInt(a.data, 10)) p.height = "100%",
				document.getElementById("myframe").contentWindow.postMessage("getHeight", "*");
			else if (a.data.toString().indexOf("px") > 0) {
				var b = parseInt(a.data, 10);
				isNaN(b) || (p.height = b + "px")
		}) : window.addEventListener("message",
		function(a) {
			if (0 === parseInt(a.data, 10)) p.height = "100%",
				document.getElementById("myframe").contentWindow.postMessage("getHeight", "*");
			else if (a.data.toString().indexOf("px") > 0) {
				var b = parseInt(a.data, 10);
				isNaN(b) || (p.height = b + "px")
		!1));
</script>
</body>
<h1>子页面</h1>
<script type="text/javascript">
	function calcPageHeight (doc) {
		var	sHeight = Math.max(doc.body.scrollHeight, doc.documentElement.scrollHeight);
		return sHeight.toString();
	calcPageHeight(document);
	window.onload = function () {
		if (top && top.location !== self.location) {
			if ((navigator.appName === 'Microsoft Internet Explorer' && navigator.appVersion .split(';')[1].replace(/[ ]/g, '') === 'MSIE7.0') ||
				(navigator.appName === 'Microsoft Internet Explorer' && navigator.appVersion .split(';')[1].replace(/[ ]/g, '') === 'MSIE6.0')) {
				if (top.name) {
					top.name = calcPageHeight(document);
			else {
				if (top.postMessage) {
					window.attachEvent ? window.attachEvent('onmessage', function (event) {
						top.postMessage(calcPageHeight(document) + 'px', '*');
					}) : window.addEventListener('message', function (event) {
						top.postMessage(calcPageHeight(document) + 'px', '*');
					}, false);
					top.postMessage(0, '*');
				else if (top.name) {
					top.name = calcPageHeight(document);