运用JavaScript构建你的第一个Metro式应用程序(onWindows 8)(二)
原文 http://blog.csdn.net/zhangxin09/article/details/6793330
先前的学习中,我们已经了解了 Metro式的 JavaScript 应用程序大致如何,以及通过使用 Microsoft Visual Studio 11 Express for Windows Developer Preview 搭建你的应用程序。接下来要探讨的是,把 Windows 平台的所提供的功能,呈现在您眼前,为扩展您的程序而准备!
- In the previous topic, you learned about Metro style app usingJavaScript, and used Microsoft Visual Studio 11 Express for WindowsDeveloper Preview to create a framework for your first app. Now it'stime to extend your application using functionality exposed by theWindows platform.
前言
- 该文是《运用 JavaScript 构建你的第一个 Metro式应用程序(on Windows8)的第二篇,如果你尚未阅读第一篇,请立刻翻阅。如果读者已经熟悉 HTML5、CSS3 和 JavaScript最好,不熟悉也没关系,不影响理解主体意思。
- This topic is the second in a series describing how to build yourfirst Windows Metro style app using JavaScriptMetro style app usingJavaScript. If you haven't already done so, read Building your firstWindows Metro style app before you read this topic. Familiarity withHTML5, Cascading Style Sheets, Level 3 (CSS3), and JavaScript ishelpful, but not essential, to understanding this topic.
加入依赖条件Capabilities
- 当用户从 Windows Store 处安装程序的时候,Windows 会对应用程序的元数据作分析,认定那些依赖条件(Capabilities)。例如,要求访问互联网、访问文档、图片、播放音频视频的时候,又或者访问如 摄像头、麦克风等的硬件时候,必须先告知用户,我这个程序需要些以上何种何种的条件才能运行。要用户首肯才能使用这些资源或设备。反之,如果没有列出的那 些资源或设备,则一定不是依赖的条件,而且一定不能够运行的(译注:意思即是未列出的就不运行)。程序所需要的依赖条件列明在程序清单 (manifest)中,具体说,就是你可以双击“Visual Studio Solution Explorer ”里面的 package.appxmanifest 文件,点击 “Capabilities” 标签页就可以选择你需要的依赖条件。默认下,你的项目都是设定有最常见的依赖条件,具备充当 Internet 客户端的条件。
- When a user installs an app from the Windows Store, Windows use theapp's metadata to figure out what capabilities it needs to run. Forexample, accessing data from the internet, accessing documents,pictures, music or videos or getting access to hardware like themicrophone or webcam. At install time, the user sees whichcapabilities an app asks for, so the app is installed only if theuser agrees for it to access those resources. If the app hasn'tlisted itself as needing access to a certain kind of resource, itisn't allowed access at run time. An app lists the capabilities itneeds in the manifest, so you can double-click on thepackage.appxmanifest file in the Visual Studio Solution Explorer,click the Capabilities tab and select the ones you need. By default,your project has the most common capability enabled, the ability toact as a client for internet service.
Windows Runtime运行时
目前为止,程序运行起来,仍属于浏览器技术的一部分内容,至今还未真正接触到 Windows 平台的运行时,特定称谓 “WindowsRuntime”,简称 “WinRT”。而 WinJS,就是允许在 JavaScript Metro 式的应用程序中,借此对象可以访问到 Windows Runtime 类库里面许许多多的功能。通过这个命名空间你还可以通过 Metr app 文档区翻阅更详尽功能。比如现在我们所使用的 Windows.Web.Syndication,用它直接获取已解析的 RSSReed,好处是不用在处理 RSS 或 ATOM 的之间上考虑怎么用 Xpath 的问题而浪费时间。
So far, we haven't really used the Windows platform on which ourapp is running, instead we used the web technologies that are alsopart of the browser. But in addition to WinJS, a Metro style appusing JavaScript can access a large amount of functionality in theWindows Runtime, broken up into namespaces that you can explore inthe Metro style app reference section. The namespace we want isWindows.Web.Syndication, because it has the SyndicationClient classthat we can use to retrieve a fully-parsed RSS feed. This saves usthe trouble of XPath or worrying about the difference between RSS andATOM.
无须太多语句或者项目引用,Metro App 下的 WinRT 元素就直接可用,这样使用 SyndicationClient 非常地简单。
The elements of the WinRT are available to Metro style apps usingJavaScript without any additional script includes or projectreferences, so using the SyndicationClient is simple:
- WinJS.Application.onmainwindowactivated = function (e) {
- if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
- // 开始下载
- downloadStatus.innerText = "downloading posts...";
- // 用WinRT 下载 RSS
- var syn = new Windows.Web.Syndication.SyndicationClient();
- var url = new Windows.Foundation.Uri("http://blogs.msdn.com/b/oldnewthing/rss.aspx");
- syn.retrieveFeedAsync(url).then(processPosts, downloadError);
- }
- }
创 建 SyndicationClient 对象之后接着创建一个 URL对象,并将其送入 RetrieveFeedAsync 进行下载。就像其他数量庞大的 Windows Runtime 函数那样,RetrieveFeedAsync 是异步的,自然也会产生“允诺Promise”。这样处理 RSS 的话更简单一些了:
After creating the SyndicationClient object, we create a URLobject and feed it to the RetrieveFeedAsync method to start thedownload. Like a large number of Windows Runtime functions,RetrieveFeedAsync is asynchronous and therefore produces a promise.Processing the RSS becomes a little bit easier now:
- function processPosts(feed) {
- // 改变指示器的状态
- downloadStatus.innerText = "";
- // 循环条目
- for (var i = 0, len = feed.items.length; i < len; i++) {
- var item = feed.items[i];
- // 向 #posts div 添加数据
- var parent = document.createElement("div");
- appendDiv(parent, item.title.text, "postTitle");
- appendDiv(parent, item.publishedDate, "postDate");
- appendDiv(parent, item.summary.text, "postContent");
- posts.appendChild(parent);
- }
- }
- function appendDiv(parent, html, className) {
- var div = document.createElement("div");
- div.innerHTML = html;
- div.className = className;
- parent.appendChild(div);
- }
回想一下,调用 xhr 的情况是提供 XML 然而并没有为我们解析XML 为对象,不同于 xhr 现在 SyndicationClient却包办搞定了,省却了循环的代码。结果虽然是一样,但其实后者会好一点。接下来介绍的数据绑定会干得更漂亮的说。
Unlike in the case of the xhr call, which provided XML but didn'tparse the RSS into objects for us, SyndicationClient does just that,simplifying our iteration code. The result looks the same, but thecode is a little nicer. And we can do even better by using templatesand data binding.
使用模板和数据绑定 UsingTemplates and Binding
看看 processPosts 函数与 appendDiv 函数结合的地方,你会发现那些静态的内容都被变量替换掉了。这种模式就是我们常说的模板(Template)。WinJS 考虑到这一功能,其语法如下所示:
If you look at the combination of the processPosts and appendDivfunction, you notice that we're mixing static content with variablesubstitution in code. This pattern of UI creation is known as atemplate. WinJS come with a similar feature and the syntax looks likethis:
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="utf-8" />
- <title>RssReader</title>
- <!-- WinJS references -->
- <link rel="stylesheet" href="/winjs/css/ui-light.css" />
- <script src="/winjs/js/base.js"></script>
- <script src="/winjs/js/ui.js"></script>
- <script src="/winjs/js/binding.js"></script>
- <script src="/winjs/js/controls.js"></script>
- <script src="/winjs/js/animations.js"></script>
- <script src="/winjs/js/uicollections.js"></script>
- <script src="/winjs/js/wwaapp.js"></script>
- <!-- RssReader references -->
- <link rel="stylesheet" href="/css/default.css" />
- <script src="/js/default.js"></script>
- </head>
- <body>
- <h1>The Old New Thing</h1>
- <div id="downloadStatus"></div>
- <div id="posts"></div>
- <div id="template" data-win-control="WinJS.Binding.Template">
- <div data-win-bind="innerText: title" class="postTitle"></div>
- <div data-win-bind="innerText: date" class="postDate"></div>
- <div data-win-bind="innerHTML: content" class="postContent"></div>
- </div>
- </body>
- </html>
欲 使用 WinJS 模板,我们必须引用一组 WinJS 的 CSS 和JavaScript 文件。WinJS 围绕 data-win-control 属性提供了若干样式和行为,等等。对于HTML 元素,HTML5 规范了一组 data-*的属性以便去特定某些程序自定义的数据(译注,HTML5 data-*可参考http://dev.w3.org/html5/spec/Overview.html#embedding-custom-non-visible-data-with-the-data-attributes)。 在该例子中,我们声明一个 WinJS.Binding.Template 的 JavaScript 构造器(constructor),该构造器获取了 div 以便为 div 登记相关的事件。顺便说一下,这也是在 WinJS 中声明一个控件的基础步骤。要触发 data-win-control 属性及其事件的执行,必须通过呼叫 WinJS.UI.processAll()。应该在哪个地方调用这个方法呢?事件 onmainwindowactivated 那里便最适合不过了。
To use WinJS templates, we must reference the bulk of the WinJSCSS and JavaScript files. These files provide the styles and behaviorfor the data-win-control attribute, among other things. HTML5 definesthe set of data-* attributes that we use for anything app-specific wewant to associate with an HTML element. In this case, we declare aJavaScript constructor function name WinJS.Binding.Template. Thisconstructor gets the associated div so that it can attach itself andprovide the necessary behavior. This is the foundation fordeclarative controls in WinJS. To cause the data-win-controlattributes to be executed, you must call WinJS.UI.processAll, whichis an excellent addition to your onmainwindowactivated event handler:
- WinJS.Application.onmainwindowactivated = function (e) {
- if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {
- // 下载
- downloadStatus.innerText = "downloading posts...";
- // use the WinRT to download the RSS
- var syn = new Windows.Web.Syndication.SyndicationClient();
- var url = new Windows.Foundation.Uri("http://blogs.msdn.com/b/oldnewthing/rss.aspx");
- syn.retrieveFeedAsync(url).then(processPosts, downloadError);
- // 执行已声明控件
- WinJS.UI.processAll();
- }
- }
调用 processAll 则就是执行 WinJS.Binding.Template 的构造器函数,构造器内部具体的过程便是查找拥有属性 data-win-bind 的那些 div,代码如下:
The call to processAll causes the WinJS.Binding.Templateconstructor to be called, which in turn parses the contents of thediv looking for data-win-bind attributes in the following format:
- <div data-win-bind=" elemAttrib1: dataProp1; elemAttrib2:dataProp2;..."></div>
如 何构成数据绑定?请注意分号前面的部分为元素属性值(attribute)与分号后面的部分为 JavaScript 属性名称(property)。不管何种对象,模板只要遇到与属性(property)相吻合的情形即会渲染出来。于是,两者形成了绑定的关系,数据转化 为特定的内容。所以模板这里的地方,我们的 processPosts 函数改为:
The attribute establishes a data binding relationship between theelement attribute name before the colon (innerText or innerHTML inour sample) and the JavaScript property name after the colon. Thisproperty name is applied to whatever object is handed to the templatewhen it is asked to render, using the data to expand variablecontent. With this template in place, our processPosts functionchanges to:
- function processPosts(feed) {
- // 改变指示器的状态
- downloadStatus.innerText = "";
- // 建立控件与模板的联系
- var template = WinJS.UI.getControl(document.getElementById("template"));
- // 循环条目
- for (var i = 0, len = feed.items.length; i < len; i++) {
- var item = feed.items[i];
- var post = {
- title: item.title.text,
- date: item.publishedDate,
- content: item.summary.text,
- };
- // 渲染每一项的模板实例
- template.render(post).then(function (element) {
- // 向 #posts div添加数据
- posts.appendChild(element);
- });
- }
- }
函
数 WinJS.UI.getControl 的参数是承托控件的元素,这里就是模板的div,getControl() 返回控件对象,实质是
JavaScript 对象,带有控件的状态和行为的对象。这里的行为就是每一项进行渲染时所消化的模板实例方法,就像刚才提到的
createElement 代码那样。模板的渲染函数是一个异步哈书,所以也需要 promise
一个函数,这里是添加帖子数据的过程。运行我们的更新程序所产生的输出与前面的过程一致,但因为模板的缩进就会看起来更清晰。在处理样式的处理时候,在
HTML中编辑好模板会比
createElement 里面写简单很多。
The call to WinJS.UI.getControl function takes the elementassociated
with the control, our template div in this case, andreturns the
JavaScript object associated with it that is acting as acontrol. This
control brings with it state and behavior. The behaviorwe
want is the render function which stamps out an instance of thetemplate
for each item we pass in, just like our createElement codewas doing
before. This happens asynchronously in the case of thetemplate's render
function, so we use a promise to append the
newlycreated element to our set of posts. Running our updated
programproduces output that looks exactly the same as before, but
ourintent, with templates, is getting clearer. It's easier to edit
thetemplate in the HTML than it is to write more and more
complicatedcreateElement
code as our styling and functionality grow.
不得不说,现在程序的样子离我们想像中的视窗应用程序差很远,列表内容太多了。实际上,多数 RSS Reader 只是会列出列表然后让你选择。我们也应该这样做,使用自带的ListView 控件做就好。
But our big list of all the content isn't as friendly as we want
aWindows app to be. In fact, most RSS reader apps show a list of
itemsand then let you select one to read. We can do that, too, using
thebuilt-in ListView control.
添加控件 Adding Controls
除了模板控件和固有的控件外,尚有 WinJS内建的若干控件可用,例如 ListView 便是一个不错的控件,能够把数据渲染成为
Grid(表格)或 List (列表)。本例中是 Grid 布局。Grid 布局可以有效地分组、组织相关的数据。Grid
里的每一项又是模板来的,这正是利用了模板的原理。不妨想像一下,首页出现时候我们不打算显示全部内容,只要求显示标题,将多个标题形成一列表,帖子的列
表。通过点击便可以看到全文内容。为此,default.html 添加了 ListView 控件,形如:
In addition to the Template control and the HTML intrinsiccontrols,
WinJS has several other built-in controls. For example, theListView
control is a useful control that knows how to arrange datainto a grid or
a list and, in the case of the grid layout, canorganize
data into groups of related-data. Each item in the grid isan expansion
of a template, as we've already seen. For example,imagine that we want
to create a list of posts, but instead ofproviding the full content on
the first page, want to click on anentry to
see the content. Adding a ListView to default.html lookslike this:
- <body>
- <h1>The Old New Thing</h1>
- <div id="downloadStatus"></div>
- <div id="template" data-win-control="WinJS.Binding.Template">
- <div data-win-bind="innerText: title" class="postTitle"></div>
- <div data-win-bind="innerText: date" class="postDate"></div>
- </div>
- <div id="posts" data-win-control="WinJS.UI.ListView"
- data-win-options="{itemRenderer: template, layout: {type: WinJS.UI.ListLayout}}"></div>
- </body>
通
过声明data-win-control 即可创建 ListView 控件,具体参数可透过data-win-options
属性其“名称-值”的结构,传入到ListView构造器(这是可选的参数)。本例中,ListView的每一项依然使用模板来决定它显示的值(没有内容
的修改版本)和布局的类型(默认为grid layout)。指定 ListView 数据的方式仍然是我们熟悉的:
Here we create the ListView control declaratively
using"data-win-control". Also, use the data-win-optionsattribute as a
set of name-value pairs that we pass as an optionalparameter to the
ListView constructor. In this case, we declare thetemplate want to
use for each item (a trimmed down version withoutthe content) and the
kind of list layout we want (grid layout is thedefault). Populating the
ListView with the data isn't very differentfrom what we've done so far:
- var postItems = [];
- function processPosts(feed) {
- downloadStatus.innerText = "";
- for (var i = 0, len = feed.items.length; i < len; i++) {
- var item = feed.items[i];
- var post = {
- title: item.title.text,
- date: item.publishedDate,
- content: item.summary.text,
- };
- postItems.push(post);
- }
- // 填入ListView 控件的数据源
- posts.winControl.dataSource = postItems;
- }
这一步,我们没有创建模板实例,而是建立data列表然后交给 ListView,即可自己渲染模板。值得一提的是,ListView 是一个聪明的控件,它会自动渲染那些实际显示的控件,现在我们创建 ListView 并填充数据:
This time, instead of creating an instance of our template foreach
item as we process it, we build up a list of data to hand to
theListView, which itself renders the template for us. But the
ListViewis much smarter about it, rendering only the template for
items thatare actually visible. Now that we created our ListView and
populatedit with data, we get:
下一步
RSS Reader 还是半成品,如果弄好了内容区,那么就完全搞定了。下一辑的《运用JavaScript创建 Metro 式程序》,将演示如何通过加入阅读模板来增强程序的外观,为你程序平添视窗应用程序的风格与特征。
We now have half of an RSS reader. We still need the other half –that
part where you can actually read the content. The next topic inthis
series, Enhancing the presentation of your app, demonstrates howto
complete your first Metro style app using JavaScript
by adding areading pane, and using a Microsoft Visual Studio template
that givesyour app the personality of Windows.
运用JavaScript构建你的第一个Metro式应用程序(onWindows 8)(二)的更多相关文章
- 运用JavaScript构建你的第一个Metro式应用程序(onWindows 8)(三)
原文 http://blog.csdn.net/zhangxin09/article/details/6793593 这是<运用 JavaScript构建你的第一个Metro式应用程序>系 ...
- 运用JavaScript构建你的第一个Metro式应用程序(on Windows 8)(一)
原文 http://blog.csdn.net/zhangxin09/article/details/6784547 作者:Chris Sells 译: sp42 原文 包括 HTML.CSS 和 ...
- React Native:使用 JavaScript 构建原生应用
[转载] 本篇为联合翻译,译者:寸志,范洪春,kmokidd,姜天意 数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生 ...
- 如何通过JavaScript构建Asp.net服务端控件
摘要 虽然ASP.NET的服务器控件一直被大家所诟病,但是用户控件(ACSX)在某些场景下还是非常有用的. 在一些极特珠的情况下,我们会使用JavaScript动态的构建页面中的控件,但假设遇到了我要 ...
- HTML5游戏开发进阶指南(亚马逊5星畅销书,教你用HTML5和JavaScript构建游戏!)
HTML5游戏开发进阶指南(亚马逊星畅销书,教你用HTML5和JavaScript构建游戏!) [印]香卡(Shankar,A.R.)著 谢光磊译 ISBN 978-7-121-21226-0 201 ...
- 深入浅出 React Native:使用 JavaScript 构建原生应用
深入浅出 React Native:使用 JavaScript 构建原生应用 链接:https://zhuanlan.zhihu.com/p/19996445 原文:Introducing React ...
- JavaScript构建(编绎)系统大比拼:Grunt vs. Gulp vs. NPM
Nicolas Bevacqua进行了一个比较JavaScript构建(编绎)系统的任务.他对三巨头: Grunt, Gulp and NPM进行了比较,并讨论了每种的优缺点. By Nicolas ...
- React Native:使用 JavaScript 构建原生应用 详细剖析
数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生的 iOS 应用——就在今天,Beta 版的仓库释出了! 基于 Pho ...
- SharePoint Framework 构建你的第一个web部件(一)
博客地址:http://blog.csdn.net/FoxDave SharePoint客户端web部件是出现在SharePoint页面的控件,但却是在浏览器本地运行的.他们是SharePoint ...
随机推荐
- sass颜色
1只定义一次颜色 {优点:可以给变量赋予不同的值: {缺点:变量名称更改与变量值混乱: 2变浅加深 /*颜色函数*/ .warning-box { background-color:lighten($ ...
- PHPStrom上传文件报502错误原因
PhpStorm是一个轻量级且便捷的PHP IDE,其自身拥有apache类似的编译器,能够在无Apache的情况下运行,很适合初学PHPStrom的朋友. 但是我发现了一个问题,那就是用PHPStr ...
- Preorder, Inorder, and Postorder非递归总结
Preorder, Inorder, and Postorder Iteratively Summarization[1] 1.Pre Order Traverse public List<In ...
- Protel在PCB中添加汉字
使用Protel 99SE的工程人员都知道Protel在PCB绘制中是不支持汉字输入的,但作为工厂生产调试的方便,不可避免的要在PCB上制作中文标示,有时为说明板子的用途,注意事项等都要输入中文丝印, ...
- js获得url内的参数
/** * js获得url内的参数 * 返回值: string or undefined * 使用方法:$_GET['from'] */ var $_GET = (function() { var s ...
- 关于chrome浏览器更新后快捷工具失效的解决方法
更新chrome浏览器到29.0时发现快捷工具的双击关闭标签页失效了,解决办法: 1.打开chrome的文件夹.C:\Program Files (x86)\Google\Chrome\Applica ...
- 全国计算机等级考试二级教程-C语言程序设计_第15章_位运算
位运算,不适用于实数,仅仅适用于整数.字符. C语言的位运算只能操作整数.字符,实数是指数方式表示的,不适用于位运算. #define _CRT_SECURE_NO_WARNINGS #include ...
- c++中使用c语言函数
在c++中使用c语言的函数时候,该函数必须在c文件中声明extern "C"才可以使用 如:extern "C" c_function_name(int, in ...
- Android AsyncHttpClient
Android Asynchronous Http Client A Callback-Based Http Client Library for Android Tweet Downloadve ...
- ping操作
如何使用Ping命令 使用Ping命令检查网络故障方法 发布时间:2012-09-13 17:42 作者:电脑百事网原创 来源:www.pc841.com 53165次阅读 电脑百事网手机版:3g ...