如何实现网页和 iframe 之间的通讯?
题干
- iframe 通讯
题解
网页和 iframe
之间的通讯是指在一个网页中嵌入了一个或多个 iframe
元素,然后需要实现网页和 iframe
,或者 iframe
之间的数据交互和方法调用。这种通讯的方式取决于网页和 iframe
是否同域,即是否具有相同的协议、域名和端口。同域的情况下,通讯相对简单,可以直接通过 window
对象的属性和方法来访问对方的 DOM
元素、全局变量和函数。跨域的情况下,通讯就需要一些特殊的技巧来实现,主要有以下几种方式:
- location.hash:这种方式是利用
URL
的哈希值(即#
后面的部分)来传递数据。哈希值的变化不会导致页面刷新,所以可以通过修改哈希值来实现数据的传递。例如,在父页面设置iframe
的src
后面加上一个数据字符串,然后在子页面中通过定时器监听location.href
的变化,就可以获取到这个数据字符串。反过来,子页面也可以修改自己的哈希值,然后父页面通过监听iframe
的onload
事件来获取子页面的哈希值。这种方式的优点是简单易用,兼容性好;缺点是数据量有限,只能传递字符串,而且可能会影响浏览器的历史记录。 - window.name:这种方式是利用
window
对象的name
属性来传递数据。window.name
的值在不同的页面(甚至不同域名)加载后依然存在,而且可以支持非常长的字符串(2MB)。例如,在子页面中设置自己的window.name
为一个数据字符串,然后再跳转到一个和父页面同域的代理页面,这样父页面就可以通过访问iframe.contentWindow.name
来获取子页面的数据。反过来,父页面也可以修改自己的window.name
,然后让子页面跳转到一个和父页面同域的代理页面,再跳回原来的页面,这样子页面就可以通过访问window.name
来获取父页面的数据。这种方式的优点是数据量大,兼容性好;缺点是需要借助代理页面,而且可能会影响浏览器的前进后退功能。 - postMessage:这种方式是利用 HTML5 提供的一个新特性,允许不同域名的窗口之间进行数据传递。使用这个方法,窗口可以向任意其他窗口发送消息,无论是否同域。例如,在父页面中调用
iframe.contentWindow.postMessage(data, origin)
方法,就可以向子页面发送一个数据对象和一个目标域名。在子页面中监听window.onmessage
事件,就可以接收到父页面发送过来的消息对象,其中包含了数据、来源域名、来源窗口等信息。反过来,子页面也可以调用window.parent.postMessage(data, origin)
方法,向父页面发送消息。这种方式的优点是安全可靠,支持任意类型的数据;缺点是兼容性较差,只能在现代浏览器中使用。 - document.domain:这种方式是利用修改
document.domain
属性来实现跨子域之间的通讯。如果两个网页一级域名相同,只是二级域名不同,那么它们可以通过设置document.domain
为一级域名来实现同域。例如,在父页面 a 中嵌入了一个子页面 b,那么它们可以分别执行document.domain = 'a.com'
,这样就可以像同域一样进行通讯了。这种方式的优点是简单有效,不影响页面的正常功能;缺点是只能用于跨子域的情况,而且有一定的安全风险。