보안 문제로 인해 서로 다른 도메인 이름의 문서는 서로의 문서에 접근할 수 없지만, 일부 때로는 이렇게 해야 할 때도 있습니다. 따라서 일반적으로 window.name, hash 또는 jsonp를 사용하여 도메인 간 액세스를 달성할 수 있습니다.
그러나 HTML5가 나왔기 때문에 postMessage를 구현하는 방법이 하나 더 있습니다. 다음은 가장 간단한 메시징 예입니다. 우리가 구현하려는 기능은 page1의 콘텐츠를 다른 Page2 페이지로 보내는 것입니다. 도메인 이름을 입력하면 page2에 해당 메시지 내용이 표시됩니다.
다음은 몇 가지 중요한 이벤트 속성입니다.
source – 메시지 소스, 메시지 전송 창/iframe.
origin – 데이터 소스를 확인하는 데 사용되는 메시지 소스의 URI(프로토콜, 도메인 이름 및 포트가 포함될 수 있음).
데이터 – 발신자가 수신자에게 보낸 데이터입니다. <br>이 세 가지 속성은 메시지 전송에 반드시 사용해야 하는 데이터입니다.
127.0.0.1 www.postmessage1.com127.0.0.1 www.postmessage2.com
<!DOCTYPE html><html><head> <title>Html5 postMessage跨文档通信</title></head><body> <input type="text" id="text"> <input type="button" id="send" value="发送"> <iframe id="ifr" src="http://www.postmessage2.com/page2.html"></iframe> <script type="text/javascript"> var text = document.getElementById('text'), send = document.getElementById('send'), ifr = window.frames[0]; //ifr = document.getElementById('ifr').contentWindow; //确保你使用的是iframe的contentWindow属性,而不是节点对象。 send.addEventListener('click',function(){ //主窗口postMessage发送消息给iframe子窗口。 //子窗口通过监听message事件来获得消息 ifr.postMessage(text.value,'http://www.postmessage2.com'); }) </script></body></html>
iframe의 src 주소는 http://www.php입니다. cn/
<!DOCTYPE html><html><head> <title></title></head> <script type="text/javascript"> //在iframe窗口中监听messages事件,并接收消息 window.addEventListener('message',function(event){ var p1 = document.getElementById('p1'); if(event.origin === 'http://www.postmessage1.com'){ p1.innerHTML += event.data +"<br>"; } }) </script><body> <h1>我是一个iframe</h1> <p id="p1"></p></body></html>다른 많은 웹 기술과 마찬가지로 데이터 소스의 적법성을 확인하지 않으면 이 기술을 사용하면 애플리케이션 보안이 매우 위험해집니다. 당신은 책임이 있습니다. window.postMessage는 PHP 대 JavaScript 기술과 같습니다. window.postMessage 멋지지 않나요?
양방향 데이터 전송도 마찬가지입니다:
<!DOCTYPE html><html><head> <title>Html5 postMessage跨文档通信</title></head><body> <input type="text" id="text"> <input type="button" id="send" value="发送"> <iframe id="ifr" src="http://www.postmessage2.com/postmessage/iframe01.html"></iframe> <script type="text/javascript"> var text = document.getElementById('text'), send = document.getElementById('send'), // ifr = window.frames[0]; ifr = document.getElementById('ifr').contentWindow; window.addEventListener('message', function(ev){ if(ev.origin === 'http://www.postmessage2.com'){ alert('从'+ ev.origin + '传过来的消息:' + ev.data); } }); send.addEventListener('click',function(){ //主窗口postMessage发送消息给iframe子窗口。 //子窗口通过监听message事件来获得消息 ifr.postMessage(text.value,'http://www.postmessage2.com'); }) </script></body></html>
다른 페이지의 코드는 다음과 같습니다:
<!DOCTYPE html><html><head> <title></title></head> <script type="text/javascript"> //在iframe窗口中监听messages事件,并接收消息 window.addEventListener('message',function(event){ var p1 = document.getElementById('p1'); if (event.origin === 'http://www.postmessage1.com') { p1.innerHTML += "来自窗口" + event.origin + event.data+"<br>" } //像主页面回送消息 event.source.postMessage("你好,这里是:" + this.location, event.origin); }); </script><body> <h1>我是一个iframe</h1> <p id="p1"></p></body></html>2 . 채널 통신
메시지 채널은 탐색 컨텍스트 간의 직접적인 양방향 통신 수단을 제공합니다. 문서 간 통신과 마찬가지로 DOM은 직접 노출되지 않습니다. 대신 파이프의 각 끝은 포트이며 데이터는 한 포트에서 전송되고 다른 포트에서 수신됩니다.
<br>그러나 채널통신을 이용하면 주소록 사이트(http://www.php.cn/)와 게임사이트(http://www.php.cn/)에서 직접 통신이 가능
.
MessageChannel 및 MessagePort 개체
MessageChannel 개체를 생성할 때 실제로 두 개의 상호 연결된 포트가 생성됩니다. 송신 측을 위해 하나의 포트가 열려 있습니다. 다른 하나는 다른 탐색 컨텍스트로 전달됩니다(상위 페이지에서 iframe 요소의 다른 하위 페이지로 전송). var mc = new MessageChannel();
각 포트는 다음 3가지 사용 가능한 메서드를 포함하는 MessagePort 개체입니다.
postMessage() 채널을 통해 메시지 보내기
start() 포트에서 수신된 메시지 발송 시작
close() 포트 닫기
MessagePort 개체에도 onmessage 이벤트가 있습니다. 속성, 이벤트 리스너 대신 이벤트 핸들러를 정의하는 데 사용할 수 있습니다.
위의 전문용어는 이해도 못하는데, 예를 들어서 이야기하는 게 더 쉽습니다.
먼저 세 개의 웹사이트를 만듭니다. 기본 웹사이트는 http://www.php.cn/이고 두 개의 하위 웹사이트는 http://www.php.cn/ 및 http://www입니다. .cn/. 이제 두 하위 웹사이트 간의 통신 프로세스를 시뮬레이션합니다. <br> 요구 사항: 하위 웹사이트 1이 로드되면 하위 웹사이트 2에 다음 메시지를 보냅니다. "(1) 기다릴 수 없습니다. 괜찮으세요? ?
", 하위 웹사이트 2가 메시지를 받으면 하위 웹사이트 1에 "(2) 걱정하지 마세요. 곧 준비될 것입니다!"라는 메시지를 반환합니다. 하위 웹페이지 1이 하위 웹사이트 2로부터 메시지를 받으면 대화 정보를 메인 페이지로 반환합니다. 하위 페이지 1의 코드<!DOCTYPE html><html><head> <title>通道通信子页面iframe01</title></head><body><script type="text/javascript"> window.onload = function(){ var mc, portMessageHandler; mc = new MessageChannel(); portMessageHandler = function(event){ alert(event.data); } //向父页面发送消息以及端口port2 window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]); //定义本页面接收到消息后,应该做的处理 mc.port1.addEventListener('message', portMessageHandler, false); //打开本页面的端口,开始监听。。。 mc.port1.start(); }</script></body></html>
<br>
메인 페이지의 코드: <!DOCTYPE html><html><head> <title>messageChannel通信</title></head><body> <h1>通道通信实例</h1> <iframe style="display: none;" src="http://localhost/test1/iframe01.html"></iframe> <iframe style="display: none;" src="http://localhost/test2/iframe02.html"></iframe> <script type="text/javascript"> window.onload = function(){ var iframes, messageHandle; iframes = window.frames; messageHandle = function(event){ if (event.ports.length > 0) { //如果有接收端口,将接收的端口与消息转发给iframe02 iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports); } } //监听第一个页面 window.addEventListener('message',messageHandle,false); } </script></body></html>
하위 페이지 2에 대한 코드:
<!DOCTYPE html><html><head> <title>通道通信子页面iframe02</title></head><body><script type="text/javascript"> window.onload = function(){ var messageHandler = function(event){ event.ports[0].postMessage(event.data + "(2)你别急呀,马上就好!"); } //子页面2接收到消息,并将新的消息转发给子页面1 window.addEventListener('message',messageHandler, false); }</script></body></html>
결과 이미지
위 데모에서는 세 페이지(메인 페이지와 두 개의 iframe 페이지)를 사용합니다. 각 페이지의 기능에 대해 이야기해 보겠습니다. <br>첫 번째는 첫 번째 iframe 페이지입니다. 세 가지 작업이 있습니다.
一是创建MessageChannel通道对象;
二是告诉主页面,我加载好了,并把端口传过去;
三是显示发送信息。
//1.创建MessageChannel通道对象mc = new MessageChannel();//2.二是告诉主页面,我加载好了,并把端口传过去;window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]);//3.显示发送信息mc.port1.addEventListener('message', portMessageHandler, false); mc.port1.start();
主页面其任务很简单就一个:告诉第二个iframe页面,端口已经打开了(第一个iframe就可以确定跟第二个iframe通信的端口了)。
// 将端口告诉其他文档iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports);
最后就是第二个iframe页面。其任务有两个:一是确定接到的消息与端口;二是将post一个新的数据和此端口保持通信了。
// 1. 接到消息与端口window.addEventListener('message',messageHandler, false);// 2. 与端口建立通道,post一个新的数据port.postMessage(message);
不同域名下的文档因为安全问题,不允许相互之间文档的访问,但是有的时候却不得不需要这样的操作。因此我们一般可以采用 window.name,hash,或者jsonp来实现跨域访问。
不过自从html5出来以后,我们又可以多一种实现方式了postMessage,下面就是一个最简单的消息传递的例子,我们要实现的功能是将page1页面中的内容,发送到不同域名下的page2页面,然后page2将对应消息内容展示出来。
下面是几个比较重要的事件属性:
source – 消息源,消息的发送窗口/iframe。
origin – 消息源的URI(可能包含协议、域名和端口),用来验证数据源。
data – 发送方发送给接收方的数据。 <br>这三个属性是消息传输中必须用到的数据。
首先我们需要两个页面,然后必须分别位于不同的域名下,当然本机肯定要有一个web服务器,接下来就通过修改host来实现不同域名访问
127.0.0.1 www.postmessage1.com127.0.0.1 www.postmessage2.com
主页http://www.php.cn/ 里面嵌套一个iframe框架
<!DOCTYPE html><html><head> <title>Html5 postMessage跨文档通信</title></head><body> <input type="text" id="text"> <input type="button" id="send" value="发送"> <iframe id="ifr" src="http://www.postmessage2.com/page2.html"></iframe> <script type="text/javascript"> var text = document.getElementById('text'), send = document.getElementById('send'), ifr = window.frames[0]; //ifr = document.getElementById('ifr').contentWindow; //确保你使用的是iframe的contentWindow属性,而不是节点对象。 send.addEventListener('click',function(){ //主窗口postMessage发送消息给iframe子窗口。 //子窗口通过监听message事件来获得消息 ifr.postMessage(text.value,'http://www.postmessage2.com'); }) </script></body></html>
iframe框架的src地址为http://www.php.cn/
<!DOCTYPE html><html><head> <title></title></head> <script type="text/javascript"> //在iframe窗口中监听messages事件,并接收消息 window.addEventListener('message',function(event){ var p1 = document.getElementById('p1'); if(event.origin === 'http://www.postmessage1.com'){ p1.innerHTML += event.data +"<br>"; } }) </script><body> <h1>我是一个iframe</h1> <p id="p1"></p></body></html>
跟其他很web技术一样,如果你不校验数据源的合法性,那使用这种技术将会变得很危险;你的应用的安全需要你对它负责。window.postMessage就像是PHP相对于JavaScript技术。window.postMessage很酷,不是吗?
双向数据传输也是一样的:
<!DOCTYPE html><html><head> <title>Html5 postMessage跨文档通信</title></head><body> <input type="text" id="text"> <input type="button" id="send" value="发送"> <iframe id="ifr" src="http://www.postmessage2.com/postmessage/iframe01.html"></iframe> <script type="text/javascript"> var text = document.getElementById('text'), send = document.getElementById('send'), // ifr = window.frames[0]; ifr = document.getElementById('ifr').contentWindow; window.addEventListener('message', function(ev){ if(ev.origin === 'http://www.postmessage2.com'){ alert('从'+ ev.origin + '传过来的消息:' + ev.data); } }); send.addEventListener('click',function(){ //主窗口postMessage发送消息给iframe子窗口。 //子窗口通过监听message事件来获得消息 ifr.postMessage(text.value,'http://www.postmessage2.com'); }) </script></body></html>
另一个页面的代码如下:
<!DOCTYPE html><html><head> <title></title></head> <script type="text/javascript"> //在iframe窗口中监听messages事件,并接收消息 window.addEventListener('message',function(event){ var p1 = document.getElementById('p1'); if (event.origin === 'http://www.postmessage1.com') { p1.innerHTML += "来自窗口" + event.origin + event.data+"<br>" } //像主页面回送消息 event.source.postMessage("你好,这里是:" + this.location, event.origin); }); </script><body> <h1>我是一个iframe</h1> <p id="p1"></p></body></html>
消息通道提供了一个直接,双向浏览上下文之间的通信手段。跟跨文档通信一样,DOM不直接暴露。取而代之,管道每端为端口,数据从一个端口发送,被另一个端口接收,。
消息通道是有用的,特别是跨多个起源的沟通。请考虑以下情形: <br>人人网上(http://www.php.cn/)嵌入了一个第三方的游戏页面(通过iframe的形式,如“人人餐厅”),同时,这个第三方的游戏页面(http://www.php.cn/)又需要从另外一个通讯录网站(http://www.php.cn/)获取用户的通讯信息。咋办?
也就是说通讯录站点要发送信息给游戏站点,根据跨文档通信,我们让父页面作为代理(也就是这里的人人网页面)(类似第一个demo)。然而,这种做法意味着通讯录站点需要有和人人网页面一样的信任级别。人人网这个社交站点需要信任每一个请求,或者为我们过滤(应该指:一个一个指定)。
但是,使用通道通信,通讯录站点(http://www.php.cn/)和游戏站点(http://www.php.cn/)可以直接沟通。
MessageChannel和MessagePort对象
当我们创建了一个MessageChannel对象,我们实际上创造了两个相互关联的端口。一个端口保持开放,为发送端。另外一个被转发到其他浏览上下文(被父页面发送到另外一个iframe元素的子页面中)。
var mc = new MessageChannel();
每一个端口就是一个MessagePort对象,包含3个可用方法:
postMessage() 通过通道发送消息
start() 开始在端口上分派接受的信息
close() 关闭端口
MessagePort对象还有onmessage事件属性,可被用来定义事件句柄而不是事件监听。
实例 <br>上面过于术语的东西我自己都看不明白,还是实例好说话。
首先建立三个网站,其中主网站为:http://www.php.cn/,另外建立两个子网站http://www.php.cn/和http://www.php.cn/。现在来模拟两个子网站之间的通信过程:
需求:当子网站1被加载完成后,向子网站2发送消息:“(1)我已经等不及了,你好了吗?<br>
”,当子网站2接收到消息后,向子网站1返回消息,“(2)你别急呀,马上就好!”。当子网页1接收到子网站2 的消息后,返回给主页面页面对话信息.
子页面1的代码
<!DOCTYPE html><html><head> <title>通道通信子页面iframe01</title></head><body><script type="text/javascript"> window.onload = function(){ var mc, portMessageHandler; mc = new MessageChannel(); portMessageHandler = function(event){ alert(event.data); } //向父页面发送消息以及端口port2 window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]); //定义本页面接收到消息后,应该做的处理 mc.port1.addEventListener('message', portMessageHandler, false); //打开本页面的端口,开始监听。。。 mc.port1.start(); }</script></body></html>
主页面的代码:
<!DOCTYPE html><html><head> <title>messageChannel通信</title></head><body> <h1>通道通信实例</h1> <iframe style="display: none;" src="http://localhost/test1/iframe01.html"></iframe> <iframe style="display: none;" src="http://localhost/test2/iframe02.html"></iframe> <script type="text/javascript"> window.onload = function(){ var iframes, messageHandle; iframes = window.frames; messageHandle = function(event){ if (event.ports.length > 0) { //如果有接收端口,将接收的端口与消息转发给iframe02 iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports); } } //监听第一个页面 window.addEventListener('message',messageHandle,false); } </script></body></html>
子页面2的代码:
<!DOCTYPE html><html><head> <title>通道通信子页面iframe02</title></head><body><script type="text/javascript"> window.onload = function(){ var messageHandler = function(event){ event.ports[0].postMessage(event.data + "(2)你别急呀,马上就好!"); } //子页面2接收到消息,并将新的消息转发给子页面1 window.addEventListener('message',messageHandler, false); }</script></body></html>
结果图 <br>
上面的demo动用了三个页面:主页面和两个iframe页面。下面说说每个页面都做了些什么:
首先是第一个iframe页面:其任务有三个,
一是创建MessageChannel通道对象;
二是告诉主页面,我加载好了,并把端口传过去;
三是显示发送信息。
//1.创建MessageChannel通道对象mc = new MessageChannel();//2.二是告诉主页面,我加载好了,并把端口传过去;window.parent.postMessage('(1)我已经等不及了,你好了吗?<br>', 'http://localhost/test1/main.html', [mc.port2]);//3.显示发送信息mc.port1.addEventListener('message', portMessageHandler, false); mc.port1.start();
主页面其任务很简单就一个:告诉第二个iframe页面,端口已经打开了(第一个iframe就可以确定跟第二个iframe通信的端口了)。
// 将端口告诉其他文档iframes[1].postMessage(event.data,'http://localhost/test2/iframe02.html', event.ports);
最后就是第二个iframe页面。其任务有两个:一是确定接到的消息与端口;二是将post一个新的数据和此端口保持通信了。
// 1. 接到消息与端口window.addEventListener('message',messageHandler, false);// 2. 与端口建立通道,post一个新的数据port.postMessage(message);
以上就是html5跨域通信之postMessage的内容,更多相关内容请关注PHP中文网(www.php.cn)!<br>
<br>