HTML5中的跨文檔消息傳遞


跨文檔消息傳送(cross-document messaging),有時候也簡稱為XDM,指的是來自不同域的頁面間傳遞消息。例如,www.w3cmm.com域中的一個頁面與一個位於內嵌框架中的p2p.w3cmm.com域中的頁面通信。在XDM機制出現之前,更穩妥地實現這種通信需要花很多功夫。XDM把這種機制規范化,讓我們能既穩妥有簡單地實現跨文檔通信。

XDM的核心是postMessage()方法。在HTML5規范中,除了XDM部分之外的其它部分也會提到這個方法名,但都是為了同一個目的:向另一個地方傳遞數據。對於XDM而言,“另一個地方”指的是包含在當前頁面中的<iframe>元素,或者由當前頁面彈出的窗口。

postMessage()方法接收兩個參數:一條消息和一個表示消息接收方來自哪個域的字符串。第二個參數對保障安全通信非常重要,可以防止瀏覽器把消息發送到不安全的地方。來看下面的例子。

var iframWindow = document.getElementById("myframe").contentWindow; iframWindow.postMessage("A secret", "http://www.w3cmm.com");

最后一行代碼嘗試向內嵌框架中發送一條消息,並指定框架中的文檔必須來源於“http://www.w3cmm.com”域。如果來源匹配,消息會傳遞到內嵌框架中;否則,postMessage()什么也不做。這一限制可以避免窗口中的位置在你不知道的情況下發生改變。如果傳給postMessage()的第二個參數是“*”,則表示可以把消息發送給來自任何域的文檔,但我們不推薦這樣做。

接收到XDM消息時,會觸發window對象的message事件。這個事件是以異步形式觸發的,因此從發送消息到接受消息(觸發接受窗口的message事件)可能要經過一段時間的延遲。觸發message事件后,傳遞給onmessage處理程序的事件對象包含以下三方面的重要信息。

data:作為postMessage()第一個參數傳入的字符串數據。
origin:發送消息的文檔所在的域,例如“http://www.w3cmm.com”。
source:發送消息的文檔的window對象的代理。這個代理對象主要用於在發送上一條消息的窗口中調用postMessage()方法。如果發送消息的窗口來自同一個域,那這個對象就是window。

接受到消息后驗證發送窗口的來源是至關重要的。就像給postMessage()方法指定第二個參數,以確保瀏覽器不會把消息發送給未知頁面一樣,在onmessage處理程序中檢測消息來源可以確保傳入的消息來自已知的頁面。基本的檢測模式如下。

var EventUtil = {     addHandler: function (element, type, handler) {         if (element.addEventListener) {             element.addEventListener(type, handler, false);         } else if (element.attachEvent) {             element.attachEvent("on" + type, handler);         } else {             element["on" + type] = handler;         }     } }; EventUtil.addHandler(window, "message", function (event) {     //確保發送消息的域是已知的域     if (event.origin == "http://www.w3cmm.com") {         //處理接收到的數據         processMessage(event.data);         //可選:向來源窗口發送回執         event.source.postMessage("Received!", "http://p2p.w3cmm.com");     } });

還是要提醒大家,event.source大多數情況下只是window對象的代理,並非實際的window對象。換句話說,不能通過這個代理對象訪問window對象的其它任何信息。記住,只通過這個代理調用postMessage()就好,這個方法永遠不存在,永遠可以調用。

XDM還有一些怪異之處。首先,postMessage()第一個參數最早是作為“永遠都是字符串”來實現的。但后來這個參數的定義改了,改成允許傳入任何數據結構。可是,並非所有瀏覽器都實現了這一變化。為保險起見,使用postMessage()時,最好還是只傳字符串。如果你想傳入結構化的數據,最佳選擇是先在要傳入的數據上調用JSON.stringify(),通過postMessage()傳入得到的字符串,然后再在onmessage事件處理程序中調用JSON.parse()。

在通過內嵌框架加載其它域的內容時,使用XDM是非常方面的。因此,在混搭和社交網絡應用中,這種傳遞消息的方法極為常用。有了XDM,包含<iframe>的頁面可以確保自身不受惡意內容的侵擾,因為它只通過XDM為嵌入的框架通信。而XDM也可以來自相同域的頁面間使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM