通过messengerJS 解决跨域的iframe自动适应高度问题(学习笔记)
前言
因为我个人并非前端工程师,所以一提到跨域就很头痛,最近有点时间研究了一下, 选择了一个比较稳妥的方案就是使用messenger.js这个js进行跨文档通信解决方案,这个还是很给力的。
适用场景
此方案适用于以下跨域情形:
- 父窗口与iframe之间通信
- 多个iframe之间通信
*上述所有情况, 都需确保对不同域的页面有修改权限, 并同时加载MessengerJS
*IE下不支持跨窗口通信
常见跨源问题有:
- 跨子域
- 跨全域
- 跨协议(HTTP与HTTPS)
此方案适用于以下跨域情形:
- 父窗口与iframe之间通信
- 多个iframe之间通信
*上述所有情况, 都需确保对不同域的页面有修改权限, 并同时加载MessengerJS
*IE下不支持跨窗口通信
常见跨源问题有:
- 跨子域
- 跨全域
- 跨协议(HTTP与HTTPS)
理念: 关于"信使"的一切
理解设计理念对实际使用有帮助作用, 高手可以直接跳到下方使用说明 : )
在跨文档通信中, 一切消息都是以字符串形式存在, 可以视其为"报文", 因此负责派送和接受信件的角色, 我们称其为"信使"(Messenger).
Messenger的职责很简单, 主要分为 发送消息(send
) 与 监听消息(listen
), 而消息的内容都是字符串. 实际使用中, 最好不要直接使用简单的字符串, 而建议使用结构化的消息(JSON String). 具体逻辑请自行实现: 发送前将json内容stringify, 收到后进行parse, 以实现消息内容的扩展性.
如何使用
-
在需要通信的文档中(父窗口和iframe们), 都确保引入MessengerJS
-
每一个文档(
document
),都需要自己的Messenger
与其他文档通信。即每一个window
对象都对应着一个,且仅有一个Messenger
对象,该Messenger
对象会负责当前window
的所有通信任务。每个Messenger
对象都需要唯一的名字,这样它们才可以知道跟谁通信。另外,推荐指定项目名称(类似命名空间的作用),以增强代码健壮性与组件复用性,避免未来与其他项目冲突。(注意: 项目名称应使用 字符串类型 )// 父窗口中 - 初始化Messenger对象
// 推荐指定项目名称, 避免Mashup类应用中, 多个开发商之间的冲突
var messenger = new Messenger(‘Parent’, ‘projectName’);// iframe中 - 初始化Messenger对象 // 注意! Messenger之间必须保持项目名称一致, 否则无法匹配通信 var messenger = new Messenger('iframe1', 'projectName'); // 多个iframe, 使用不同的名字 var messenger = new Messenger('iframe2', 'projectName');
-
在发送消息前,确保目标文档已经监听了消息事件。
// iframe中 - 监听消息
// 回调函数按照监听的顺序执行
messenger.listen(function(msg){
alert("收到消息: " + msg);
}); -
父窗口想给iframe发消息,它怎么知道iframe的存在呢?添加一个消息对象吧。
// 父窗口中 - 添加消息对象, 明确告诉父窗口iframe的window引用与名字
messenger.addTarget(iframe1.contentWindow, ‘iframe1’);// 父窗口中 - 可以添加多个消息对象 messenger.addTarget(iframe2.contentWindow, 'iframe2');
-
一切ready,发消息吧~发送消息有两种方式。 (以父窗口向iframe发消息为例)
// 父窗口中 - 向单个iframe发消息
messenger.targets[‘iframe1’].send(msg1);
messenger.targets[‘iframe2’].send(msg2);// 父窗口中 - 向所有目标iframe广播消息 messenger.send(msg);
-
现在看到iframe收到消息的alert提示了吗?
以上是官方文档的内容
官方也给了一个案例提供我们研究。为了方便初学者学习,在这里,我自己写了一个案例,帮助大家很快的理解和使用。
本人案例笔记
操作步骤:
创建父工程
工程目录结构
WebDemo
ParentPage讲解
父页面代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>解决跨域问题-postMessage方法自适应高度</title>
</head>
<body>
<iframe id="childFrame" src="http://1.0.7.103:49707/domain/children.html" frameborder="0" width="100%">
</iframe>
<button onclick="sendMessage('你好')">发送你好的信息</button>
</body>
<script src="messenger.js"></script>
<script>
debugger;
var messenger = new Messenger('parent', 'MessengerDemo');
var childFrame = document.getElementById('childFrame');
messenger.addTarget(childFrame.contentWindow, 'childFrame');
var sendMessage = function(v){
messenger.targets['childFrame'].send(v);
}
</script>
</html>
创建子工程
工程目录结构
children 代码说明
左侧的为子工程源码,右侧为主工程源码
从以上图可以看出对应关系。
children源代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域自适应高度-postMessage方式例子</title>
</head>
<body>
<div id="test"></div>
</body>
<script type="text/javascript" src="messenger.js" ></script>
<script>
debugger;
var messenger = new Messenger('childFrame', 'MessengerDemo');
messenger.addTarget(window.parent, 'parent');
messenger.listen(function (msg) {
//alert(msg);
console.log(msg);
})
</script>
</html>
点击后子页面既可收到跨域信息。
例子 通过Messenger.JS 解决iframe 自适应高度问题。
思路
主页面通过对子页面的监听,自动调整高度。
代码
主页面源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>解决跨域问题-postMessage方法自适应高度</title>
</head>
<body>
<iframe id="childFrame" src="http://192.168.43.33/domain/children.html" scrolling="no" frameborder="0" width="100%">
</iframe>
<button onclick="sendMessage('你好-我是父页面')">发送你好的信息</button>
</body>
<script src="messenger.js"></script>
<script>
debugger;
var messenger = new Messenger('parent', 'MessengerDemo');
var childFrame = document.getElementById('childFrame');
messenger.addTarget(childFrame.contentWindow, 'childFrame');
var sendMessage = function(v){
messenger.targets['childFrame'].send(v);
}
messenger.listen(function (msg) {
var cf = document.getElementById("childFrame");
var heightMs =parseInt(msg)+20;
//alert(heightMs);
cf.height = heightMs+"px";
});
</script>
</html>
子页面源码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>跨域自适应高度-postMessage方式例子</title>
</head>
<body>
<div id="test"></div>
<button onclick="addDiv()" value="增加DIV增大子页面长度">增加DIV增大子页面长度</button></body>
<script type="text/javascript" src="messenger.js" ></script>
<script>
var messenger = new Messenger('childFrame', 'MessengerDemo');
messenger.addTarget(window.parent, 'parent');
var addDiv = function(){
var div = document.createElement("div")
var nodeText = document.createTextNode("新增加一行数据新增加一行数据新增加一行数据新增加一行数据新增加一行数据新增加一行数据");
div.appendChild(nodeText);
document.getElementById("test").appendChild(div);
messenger.targets['parent'].send(document.body.offsetHeight);
}
</script>
</html>