页面通信/数据交换的小结

页面通信方法的小结,及跨域问题的解决方法。

页面间通信方法

  • 父页面对于同源的iframe和window.open(URL,name,features,replace)打开的窗口能访问其 DOM。
  • 存储在浏览器中的数据,如Cookie,localStorageIndexedDB,以源进行分割。每个源都拥有自己单独的存储空间,一个源中的Javascript脚本不能对属于其它源的数据进行读写操作。
  • postMessage方法可以跨文档通信/通道通信。
  • Ajax请求等前后端通信方法。

有些方法有着同源限制,所以主要记录一下跨域问题及解决。

同源

判断同源的条件

  • 相同的协议
  • 相同的域名(主机)
  • 相同的端口号(IE例外)

非同源的限制

  • 无法读取 cookie, localStorage, indexDB
  • 不能获得不同源的窗口或框架的DOM(可拿到引用但访问内容受限)
  • ajax 调用无法正常接收数据

不受同源限制的

  • 提交表单
  • 由 DOM 发起的网络请求(例如:img, script,CSS 等 DOM 元素加载资源)(能使用元素的src属性发信息,能获取静态资)

跨域通信方法

document.domain

脚本可以将 document.domain 的值设置为其当前域*或其当前域的超级域*。故,若主域名相同时,可通过设置domain解决跨域问题。需要注意的是:浏览器单独保存端口号。对document.domain的任何赋值操作,包括document.domain = document.domain都会以null值覆盖掉原来的端口号。赋值时必须带上端口号,以确保端口号不会为null。(若想共享cookie,也可在 response 里修改 cookie 的 domain 。)

Web Messaging API

message事件

该事件的事件对象 event 有以下5个属性:

  • event.data: 接收到的数据
  • event.origin: 数据发送方的源
  • event.lastEventId: 当前的消息事件的唯一标识符
  • event.source: 数据发送方的窗口对象的引用
  • event.ports: 发送消息的MessagePort](http://dev.w3.org/html5/postmsg/#messageport)对象

不支持事件冒泡;不能取消;没有默认行为。

postMessage方法
跨文档通信

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

windowObj是其他窗口的一个引用,可以是iframe 的 contentWindow 属性、执行 window.open 返回的窗口对象、或者是 window.frames等。

参数:message(发送的消息,可以是字符串、结构对象、数据对象、数组等);targetOrigin(接收文档的来源);transfer(常用于通道通信中,是一串和message 同时传递的 Transferable 对象. 这些对象的所有权将被转移给消息的接收方,而发送一方将不再保有所有权)

通过 window.postMessage,也能使不同窗口的 LocalStorage 进行交互。

通道通信

多用于多源之间的通信。通道消息可以使不同浏览上下文中的代码通过端口直接通信。新建一个 MessageChannel 对象 ,实际上就创造了两个相关联的端口(port1,port2) ,一个端口在发送方并保持开放,另一个被传送到接收方(otherwindow/otherworker)的context。同样使用postMessage方法和onmessage事件监听。

本节Refer: https://dev.opera.com/articles/window-postmessage-messagechannel/

window.name

window.name属性可以存储数据(2MB左右),且无跨域限制(window对象没有改变的话,该 window 跳转的网页都能读取 window.name )。需要一个代理页面。如:当页面 A 想要从另一个源获取资源,首先在自己的页面上创建一个隐藏的 iframe B(或开一个窗口),将 B 指向外部资源或服务(例如:otherdomain.com/data.php),B 加载完成之后,把响应的数据附加到 window.name 上。再将页面导航(location 变更)到任何一个与 A 同源的页(即代理页面),这时 A 就可以直接获取到 B 的 name 属性值。缺点是需不断查询数据是否加载完。

使用片段标识符

片段标识符指 url 中 # 之后的部分,即location.hash。 使用片段标识符依托于以下几个关键点:

  1. 改变 location.hash不会触发页面的刷新的
  2. 不同源的页面间虽然不能操作 iframe 中的 windowdom,但是可以改变 iframe 的 url
  3. window 对象可以监听 hashchange 事件

当 A 想要向 B 发送信息时,它可以修改 B 的 hash 值。B 中的函数将轮询自身的 hash 值,找出 A 发送的是什么,然后它可以用同样的方式回复 A。如果 A 想接收这条消息,也需要轮询其本身的 hash 值。

refer: https://www.ibm.com/developerworks/cn/web/wa-crossdomaincomm/

Ajax跨域

  • CORS

    使用自定义的HTTP头部让浏览器与服务器沟通。附加一个Origin头部。服务器也要进行相应设置。

  • JSONP

    动态插入script标签,通过script标签引入一个js文件,这个js文件载入成功后会执行我们在url参数中指定的函数,并且会把我们需要的json数据作为参数传入。类似的还有使用图像Ping。实质上是通过DOM请求静态资源,不受同源限制。

More

这篇主要讲的是前端页面的通信,因为涉及跨域问题,所以也简单记录了Ajax的跨域。对于前后端的信息交互,可以参考:前后端数据交互