HTML5新特性之Communication
2015-05-31 22:06
246 查看
Communication是众多HTML5新特性中比较重要的一个,它提供一种基于安全策略的跨站交互的机制,即使来自不同的站点的应用之间也能自由的通信,正是这一特性的出现,使得不同站点内容的集成简化了许多。
我们都知道,基于安全方面的考虑,浏览器会合理地限制脚本的执行,禁止访问其他站点的数据服务或操作非本站点的DOM对象,这些安全机制在一定程度上消除了安全攻击的隐患,但也给前端开发者带了一定的麻烦,我们不得不采取一些“曲线救国”的手段来实现跨站通信的功能。但随着HTML5的逐渐成熟,我们使用Communication API去解决这些问题,一切都是那么简单。今天我们主要来介绍一下Communication API中跨文档消息通信以及应用案例。
我们这里所要讲解的是一个跨站资源整合的例子,假如我们的站点需要为用户呈现一些多元化的资源信息,这些资源可能不是由我们自己提供,而是和其他的站点合作,由他们分别来提供,就像下面图示那样,在主站点有一个搜索框,然后下面嵌入合作站点的两个信息展示页面,一个是新闻站点,另外一个是股票站点,分别显示不同的信息,如果用户在主站点输入关键字并点击搜索,内嵌的合作站点就会受到消息,然后分别去服务端请求数据,最终将搜索结果呈现到主站点。
![](http://img.blog.csdn.net/20150523222413025)
![](http://img.blog.csdn.net/20150523222441090)
我们可以看到搜索前后的变化,当用户用关键字搜索时,会同时触发两个站点的搜索操作,然后每个站点搜索完成后都会将自己搜索结果数量汇总到主站点,所以主站显示8个搜索结果,是两个内嵌站点结果数量之和。
现在让我们来看看主站点页面的结构:
我们知道,如果URL中的协议、域名和端口中有任何一个不同,就认为是跨域的,所以很明显,我们嵌入的两个页面都是跨域资源,主页面是无法通过脚本去操作内嵌页面DOM的,自然无法执行内部的代码,如图所示:
![](http://img.blog.csdn.net/20150523194002441)
那么我们如何能够通知内嵌页面去执行相应的操作呢,这就涉及到了一个非常重要的API,那就是postMessage函数:
通过postMessage函数,消息就被发送到内嵌站点页面了,那么我们如何接受消息呢?我们可以注册message事件,比如我们可以在news的页面中这样处理:
现在就让我们来看看主站点是如何处理这个消息的,我们对主站点的逻辑稍加修改:
同样,我们是注册了message事件,并判断消息源是否为news或stocks,我们还添加了一个resultNum变量,每次开始搜索时置0,然后接收到news或stocks返回的结果数量后将结果数量显示出来。搜索的整个过程如图所示:
![](http://img.blog.csdn.net/20150524110900637)
这个过程看起来似乎很简单,不过要在本地运行起来,还需要一些配置,接下来我们就讲解一下如何配置及运行这个实例。
概况来讲,我们需要以下几个步骤:
1. 修改hosts,配置映射域名
2. 安装基于Node.js平台的http-server简单Web服务包
3. 分别以不同端口启动三个应用
首先,修改我们本机的hosts,添加一下三行配置,保证我们通过指定域名访问时,系统会自动映射到本机:
![](http://img.blog.csdn.net/20150524114251567)
所以我们在Communication目录下,分别进入这三个子目录,然后启动各自的服务,只需执行以下命令:
我们都知道,基于安全方面的考虑,浏览器会合理地限制脚本的执行,禁止访问其他站点的数据服务或操作非本站点的DOM对象,这些安全机制在一定程度上消除了安全攻击的隐患,但也给前端开发者带了一定的麻烦,我们不得不采取一些“曲线救国”的手段来实现跨站通信的功能。但随着HTML5的逐渐成熟,我们使用Communication API去解决这些问题,一切都是那么简单。今天我们主要来介绍一下Communication API中跨文档消息通信以及应用案例。
我们这里所要讲解的是一个跨站资源整合的例子,假如我们的站点需要为用户呈现一些多元化的资源信息,这些资源可能不是由我们自己提供,而是和其他的站点合作,由他们分别来提供,就像下面图示那样,在主站点有一个搜索框,然后下面嵌入合作站点的两个信息展示页面,一个是新闻站点,另外一个是股票站点,分别显示不同的信息,如果用户在主站点输入关键字并点击搜索,内嵌的合作站点就会受到消息,然后分别去服务端请求数据,最终将搜索结果呈现到主站点。
我们可以看到搜索前后的变化,当用户用关键字搜索时,会同时触发两个站点的搜索操作,然后每个站点搜索完成后都会将自己搜索结果数量汇总到主站点,所以主站显示8个搜索结果,是两个内嵌站点结果数量之和。
现在让我们来看看主站点页面的结构:
<div> <input id="keyword" type="text"/> <button onclick="search()">Search</button> <span id="results"> <b id="resultsNum"></b> results. </span> </div> <!--news module--> <iframe id='newsModule' src="http://test.news.com:8082/index.html"></iframe> <!--stocks module--> <iframe id="stocksModule" src="http://test.stocks.com:8083/index.html"></iframe>从上面代码可以看出,我们用了两个iframe分别引入了两个不同站点的页面,而http://test.integration.com:8081正是我们的主站点,它将两个不同站点的资源整合在了一起。
我们知道,如果URL中的协议、域名和端口中有任何一个不同,就认为是跨域的,所以很明显,我们嵌入的两个页面都是跨域资源,主页面是无法通过脚本去操作内嵌页面DOM的,自然无法执行内部的代码,如图所示:
那么我们如何能够通知内嵌页面去执行相应的操作呢,这就涉及到了一个非常重要的API,那就是postMessage函数:
function search() { var keyword = document.getElementById('keyword').value; var newsOrigin = 'http://test.news.com:8082'; var stocksOrigin = 'http://test.stocks.com:8083'; document.getElementById('newsModule').contentWindow.postMessage({keyword: keyword}, newsOrigin); document.getElementById('stocksModule').contentWindow.postMessage({keyword: keyword}, stocksOrigin); }可以看到,当执行search函数时,我们先回取到用户输入的关键字,然后分别获取到每个iframe的window对象,然后调用postMessage函数,该函数有两个重要的参数,第一个是要传递的数据,可以传递字符串或者对象;第二个参数指定目标的源,包括协议、域名以及端口。
通过postMessage函数,消息就被发送到内嵌站点页面了,那么我们如何接受消息呢?我们可以注册message事件,比如我们可以在news的页面中这样处理:
var searchFromServer = function(keyword, callback) { //fake search logic var resultsNum = 3; document.getElementById('display').textContent = resultsNum + ' records by: ' + keyword; callback(resultsNum); }; window.addEventListener('message', function(e) { var allowed = { 'http://test.integration.com:8081': true }; if (allowed[e.origin]) { var keyword = e.data.keyword; searchFromServer(keyword, function(resultsNum) { window.top.postMessage({resultsNum: resultsNum}, 'http://test.integration.com:8081'); }); } }, false);可以看到,内嵌的news站点页面中注册了message事件并指定了处理函数,事件参数e包含两个重要属性,origin表示消息发送方的origin,data表示消息中包含的数据,其中origin非常重要,我们可以判断消息来源是否为合作伙伴的站点,这样就可以过滤一些非法请求了。接下来,searchFromServer函数被调用,这个函数模拟了服务器请求,直接指定3条搜索结果,并传递到回调函数中,而在回调函数中,通过window.top获取到最顶层的window对象,然后向其发送一条消息,将搜索结果数量作为数据传送到我们的主站点。
现在就让我们来看看主站点是如何处理这个消息的,我们对主站点的逻辑稍加修改:
var resultsNum; function search() { resultsNum = 0; var keyword = document.getElementById('keyword').value; var newsOrigin = 'http://test.news.com:8082'; var stocksOrigin = 'http://test.stocks.com:8083'; document.getElementById('newsModule').contentWindow.postMessage({keyword: keyword}, newsOrigin); document.getElementById('stocksModule').contentWindow.postMessage({keyword: keyword}, stocksOrigin); } window.addEventListener('message', function(e) { var allowed = { 'http://test.news.com:8082': true, 'http://test.stocks.com:8083': true }; if (allowed[e.origin]) { resultsNum += e.data.resultsNum; document.getElementById('results').style.display = 'inLine'; document.getElementById('resultsNum').textContent = resultsNum; } }, false);
同样,我们是注册了message事件,并判断消息源是否为news或stocks,我们还添加了一个resultNum变量,每次开始搜索时置0,然后接收到news或stocks返回的结果数量后将结果数量显示出来。搜索的整个过程如图所示:
这个过程看起来似乎很简单,不过要在本地运行起来,还需要一些配置,接下来我们就讲解一下如何配置及运行这个实例。
概况来讲,我们需要以下几个步骤:
1. 修改hosts,配置映射域名
2. 安装基于Node.js平台的http-server简单Web服务包
3. 分别以不同端口启动三个应用
首先,修改我们本机的hosts,添加一下三行配置,保证我们通过指定域名访问时,系统会自动映射到本机:
127.0.0.1 test.news.com 127.0.0.1 test.stocks.com 127.0.0.1 test.integration.com接下来,我们需要配置Web服务,请确保我们本机已经安装Node.js环境,然后执行下面的命令:
npm install http-server -g最后,我们就需要分别启动三个站点了,我们的目录结构如下:
所以我们在Communication目录下,分别进入这三个子目录,然后启动各自的服务,只需执行以下命令:
cd integration http-server -p 8081 cd news http-sever -p 8082 cd stocks http-server -p 8083大功告成,现在我们访问test.integration.com:8081就可以看到我们上面展示的页面了。不过最后需要注意的是,我们需要使用比较新的浏览器才支持这个新特性,当然我们在实际开发中可以用下面这种方式检测浏览器的支持情况:
var isMessageSupported = 'postMessage' in window;我们今天先到这里,希望大家能够亲自搭建环境并测试一下上面介绍的示例,并能够体会并掌握跨文档消息通信的新特性。
相关文章推荐
- Qunee for HTML5 V2.0新版本发布
- 学习 HTML5-目录
- html5在canvas中插入图片
- 36个炫丽的html5 canvas展示
- h5 播放器 -3
- h5 播放器 -2
- HTML5.0笔记 (一)
- HTML5游戏开发-扫雷及其算法研究
- HTML5----移动head,meta标签属
- HTML5新增标签总结和说明
- 检测浏览器是否支持HTML5视频
- HTML5学习之FileReader接口
- 使用 HTML5 WebSocket 构建实时 Web 应用
- [150529]国内最火的五款HTML5前端开发框架
- 【Html5 WebSocket】WebSocket事件
- HTML5 知识点(全)
- #HTML5开源源码#网页版植物大战僵尸
- HTML5中meta属性的使用详解
- HTML5和HTML属性及元素整理
- HTML5开发手机应用--viewport的作用