下面是对使用JavaScript的Bing Maps Trip Optimizer示例的介绍,讲述应用的JavaScript部分组织形式,本地的上下文和网络上下文之间的通信。
WinRT需要访问网络的代码,下面是一些需要访问网络的活动示例。
q 加载一个外部JavaScript文件,比如Bing Maps的AJAX控件。
q 加载外部CSS。
q 使用XmlHttpRequest。
Bing Maps Trip Optimizer将界面分为两个HTML文件,即“default.html”和“mapControl.html”,“default.html”属于local context(本地上下文),其可以引用WinRT(这个包括自定义C++的WinRT组件,不过不能访问网络),“default.html”表示应用的主页面。“mapControl.html”可称为web context(网络上下文),因为其可访问网络,但不能访问WinRT。“mapControl.html”是一个local context的内嵌框架。下图是local context和web context间的关系。
注意:就安全性而言,在一个单独的模块中维护web代码,同样会增加应用的安全性。可能的话有必要验证从web context接收到local context的内容,这样可以减少发生安全性缺陷的可能,比如缓冲区溢出。
接下来在local context中引用web context。local context(default.html)中body标签定义一个内嵌框架(iframe标签)来放置web context,代码如下。
<body οnlοad="OnLoad();" style="padding: 0; margin: 0; position: absolute; left: 0px;
width: 100%; top: 0px; height: 100%; overflow: hidden">
<iframe id="mapFrame" src="ms-appx-web:///mapControl.html"
style="position: absolute; left: 0px; width: 100%; top: 0px; height: 100%; overflow: hidden">
</iframe>
</body>
在JavaScript的Metro风格应用中引用代码文件时,使用这样的语法:src = "ms-appx-web://<package-name>/<file-name>" 。如果目标文件是和调用文件同一个包的一部分,可以在应用的manifest文件中找到包名。
再来说上下文间的通信。local context和web context使用跨文档信息通信,在上下文通信前,其必须首先注册通信事件。“default.html”和“mapControl.html”为body标签中的“onload”属性指定一个“OnLoad”函数,“OnLoad”函数调用“addEventListener”方法监听消息类型事件,并将这些消息路由发送到“receiveMessage”函数,代码如下。
function OnLoad() {
window.addEventListener("message", receiveMessage, false);
}
注意:Bing Maps Trip Optimizer使用跨文档消息传递,因为对一个上下文而言,其不能直接访问其他上下文的DOM。
在上下文注册了通信事件后,可以使用“postMessage”方法通信。这个方法发送一个跨文档消息,而消息是路由到消息事件处理函数。由于跨文档消息是基于文本的,应用和web上下文使用“JSON.stringify”函数将信息序列化到JSON文本中。当一个上下文收到一个消息时,它会调用“JSON.parse”函数将JSON文本字段反序列化。
为了说明上下文通信的方式,考虑让web context通信local context来初始化自定义C++的WinRT组件(回忆一下可以想到,web context不能直接和WinRT组件交互),web context(即mapControl.html)中定义的“OnLoad”函数在初始化期间被调用,对mapControl.html页面的部分代码如下。
function OnLoad() {
window.addEventListener("message", receiveMessage, false);
}
“OnLoad”函数调用“optimizerLoad”函数,“optimizerLoad”函数通信local context来初始化C++的WinRT组件,部分代码如下。
rho, iterations, parallel) {
var message = {
"invoke": "optimizeTrip", "locations": locations, "TravelMode": TravelMode, "Optimize": Optimize, "BingMapsKey": BingMapsKey,
"alpha": alpha, "beta": beta, "rho": rho, "iterations": iterations, "parallel": parallel
};
window.parent.postMessage(JSON.stringify(message), '*');
}
从web context,而不是直接从local context初始化WinRT组件的加载,这样确保web context和local context都在创建WinRT组件前被加载。