运用JavaScript构建你的第一个Metro式应用程序(onWindows 8)(二)

简介:

先前的学习中,我们已经了解了 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:

[javascript]  view plain copy
  1. WinJS.Application.onmainwindowactivated = function (e) {  
  2.     if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {  
  3.         // 开始下载  
  4.         downloadStatus.innerText = "downloading posts...";  
  5.   
  6.         //  用WinRT 下载 RSS  
  7.         var syn = new Windows.Web.Syndication.SyndicationClient();  
  8.         var url = new Windows.Foundation.Uri("http://blogs.msdn.com/b/oldnewthing/rss.aspx");  
  9.         syn.retrieveFeedAsync(url).then(processPosts, downloadError);  
  10.     }  
  11. }  

创建 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:

 

[javascript]  view plain copy
  1. function processPosts(feed) {  
  2.   // 改变指示器的状态  
  3.   downloadStatus.innerText = "";  
  4.   
  5.   // 循环条目  
  6.   for (var i = 0, len = feed.items.length; i < len; i++) {  
  7.     var item = feed.items[i];  
  8.     // 向 #posts div 添加数据  
  9.     var parent = document.createElement("div");  
  10.     appendDiv(parent, item.title.text, "postTitle");  
  11.     appendDiv(parent, item.publishedDate, "postDate");  
  12.     appendDiv(parent, item.summary.text, "postContent");  
  13.     posts.appendChild(parent);  
  14.   }  
  15. }  
  16.   
  17. function appendDiv(parent, html, className) {  
  18.     var div = document.createElement("div");  
  19.     div.innerHTML = html;  
  20.     div.className = className;  
  21.     parent.appendChild(div);  
  22. }  

回想一下,调用 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:

 

[html]  view plain copy
  1. <!DOCTYPE html>  
  2. <html>  
  3. <head>  
  4.     <meta charset="utf-8" />  
  5.     <title>RssReader</title>  
  6.     <!-- WinJS references -->  
  7.     <link rel="stylesheet" href="/winjs/css/ui-light.css" />  
  8.     <script src="/winjs/js/base.js"></script>  
  9.     <script src="/winjs/js/ui.js"></script>  
  10.     <script src="/winjs/js/binding.js"></script>  
  11.     <script src="/winjs/js/controls.js"></script>  
  12.     <script src="/winjs/js/animations.js"></script>  
  13.     <script src="/winjs/js/uicollections.js"></script>  
  14.     <script src="/winjs/js/wwaapp.js"></script>  
  15.     <!-- RssReader references -->  
  16.     <link rel="stylesheet" href="/css/default.css" />  
  17.     <script src="/js/default.js"></script>  
  18. </head>  
  19. <body>  
  20.     <h1>The Old New Thing</h1>  
  21.     <div id="downloadStatus"></div>  
  22.     <div id="posts"></div>  
  23.     <div id="template" data-win-control="WinJS.Binding.Template">  
  24.         <div data-win-bind="innerText: title" class="postTitle"></div>  
  25.         <div data-win-bind="innerText: date" class="postDate"></div>  
  26.         <div data-win-bind="innerHTML: content" class="postContent"></div>  
  27.     </div>  
  28. </body>  
  29. </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:

[javascript]  view plain copy
  1. WinJS.Application.onmainwindowactivated = function (e) {  
  2.     if (e.detail.kind === Windows.ApplicationModel.Activation.ActivationKind.launch) {  
  3.         // 下载  
  4.         downloadStatus.innerText = "downloading posts...";  
  5.   
  6.         // use the WinRT to download the RSS  
  7.         var syn = new Windows.Web.Syndication.SyndicationClient();  
  8.         var url = new Windows.Foundation.Uri("http://blogs.msdn.com/b/oldnewthing/rss.aspx");  
  9.         syn.retrieveFeedAsync(url).then(processPosts, downloadError);  
  10.   
  11.         // 执行已声明控件  
  12.         WinJS.UI.processAll();  
  13.     }  
  14. }  

调用 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:

 

[html]  view plain copy
  1. <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:

[javascript]  view plain copy
  1. function processPosts(feed) {  
  2.   // 改变指示器的状态  
  3.   downloadStatus.innerText = "";  
  4.   
  5.   // 建立控件与模板的联系  
  6.   var template = WinJS.UI.getControl(document.getElementById("template"));  
  7.   
  8.   // 循环条目  
  9.   for (var i = 0, len = feed.items.length; i < len; i++) {  
  10.     var item = feed.items[i];  
  11.     var post = {  
  12.       title: item.title.text,  
  13.       date: item.publishedDate,  
  14.       content: item.summary.text,  
  15.     };  
  16.   
  17.     // 渲染每一项的模板实例  
  18.     template.render(post).then(function (element) {  
  19.       // 向 #posts div添加数据  
  20.       posts.appendChild(element);  
  21.     });  
  22.   }  
  23. }  

函数 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:

[html]  view plain copy
  1. <body>  
  2.     <h1>The Old New Thing</h1>  
  3.     <div id="downloadStatus"></div>  
  4.     <div id="template" data-win-control="WinJS.Binding.Template">  
  5.         <div data-win-bind="innerText: title" class="postTitle"></div>  
  6.         <div data-win-bind="innerText: date" class="postDate"></div>  
  7.     </div>  
  8.     <div id="posts" data-win-control="WinJS.UI.ListView"  
  9.          data-win-options="{itemRenderer: template, layout: {type: WinJS.UI.ListLayout}}"></div>  
  10. </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:

 

[javascript]  view plain copy
  1. var postItems = [];  
  2.   
  3. function processPosts(feed) {  
  4.     downloadStatus.innerText = "";  
  5.   
  6.     for (var i = 0, len = feed.items.length; i < len; i++) {  
  7.         var item = feed.items[i];  
  8.         var post = {  
  9.             title: item.title.text,  
  10.             date: item.publishedDate,  
  11.             content: item.summary.text,  
  12.         };  
  13.         postItems.push(post);  
  14.     }  
  15.   
  16.     // 填入ListView 控件的数据源  
  17.     posts.winControl.dataSource = postItems;  
  18. }  

这一步,我们没有创建模板实例,而是建立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.

 

原文地址



本文转自Work Hard Work Smart博客园博客,原文链接:http://www.cnblogs.com/linlf03/archive/2012/02/10/2345197.html,如需转载请自行联系原作者

目录
相关文章
|
13天前
|
Web App开发 JavaScript 前端开发
深入浅出Node.js:从零开始构建后端服务
【10月更文挑战第42天】在数字时代的浪潮中,掌握一门后端技术对于开发者来说至关重要。Node.js,作为一种基于Chrome V8引擎的JavaScript运行环境,允许开发者使用JavaScript编写服务器端代码,极大地拓宽了前端开发者的技能边界。本文将从Node.js的基础概念讲起,逐步引导读者理解其事件驱动、非阻塞I/O模型的核心原理,并指导如何在实战中应用这些知识构建高效、可扩展的后端服务。通过深入浅出的方式,我们将一起探索Node.js的魅力和潜力,解锁更多可能。
|
10天前
|
存储 缓存 JavaScript
如何优化Node.js应用的内存使用以提高性能?
通过以上多种方法的综合运用,可以有效地优化 Node.js 应用的内存使用,提高性能,提升用户体验。同时,不断关注内存管理的最新技术和最佳实践,持续改进应用的性能表现。
|
27天前
|
JavaScript 中间件 关系型数据库
构建高效的后端服务:Node.js 与 Express 的实践指南
在后端开发领域,Node.js 与 Express 的组合因其轻量级和高效性而广受欢迎。本文将深入探讨如何利用这一组合构建高性能的后端服务。我们将从 Node.js 的事件驱动和非阻塞 I/O 模型出发,解释其如何优化网络请求处理。接着,通过 Express 框架的简洁 API,展示如何快速搭建 RESTful API。文章还将涉及中间件的使用,以及如何结合 MySQL 数据库进行数据操作。最后,我们将讨论性能优化技巧,包括异步编程模式和缓存策略,以确保服务的稳定性和扩展性。
|
16天前
|
JSON JavaScript API
深入浅出Node.js:从零开始构建RESTful API
【10月更文挑战第39天】 在数字化时代的浪潮中,API(应用程序编程接口)已成为连接不同软件应用的桥梁。本文将带领读者从零基础出发,逐步深入Node.js的世界,最终实现一个功能完备的RESTful API。通过实践,我们将探索如何利用Node.js的异步特性和强大的生态系统来构建高效、可扩展的服务。准备好迎接代码和概念的碰撞,一起解锁后端开发的新篇章。
|
1月前
|
资源调度 前端开发 数据可视化
构建高效的数据可视化仪表板:D3.js与React的融合之道
【10月更文挑战第25天】在数据驱动的时代,将复杂的数据集转换为直观、互动式的可视化表示已成为一项至关重要的技能。本文深入探讨了如何结合D3.js的强大可视化功能和React框架的响应式特性来构建高效、动态的数据可视化仪表板。文章首先介绍了D3.js和React的基础知识,然后通过一个实际的项目案例,详细阐述了如何将两者结合使用,并提供了实用的代码示例。无论你是数据科学家、前端开发者还是可视化爱好者,这篇文章都将为你提供宝贵的洞见和实用技能。
55 5
|
29天前
|
数据可视化 JavaScript 前端开发
数据可视化进阶:D3.js在复杂数据可视化中的应用
【10月更文挑战第26天】数据可视化是将数据以图形、图表等形式呈现的过程,帮助我们理解数据和揭示趋势。D3.js(Data-Driven Documents)是一个基于JavaScript的库,使用HTML、SVG和CSS创建动态、交互式的数据可视化。它通过数据驱动文档的方式,将数据与DOM元素关联,提供高度的灵活性和定制性,适用于复杂数据的可视化任务。 示例代码展示了如何使用D3.js创建一个简单的柱状图,展示了其基本用法。D3.js的链式调用和回调函数机制使代码简洁易懂,支持复杂的布局和交互逻辑。
67 3
|
20天前
|
JavaScript 前端开发 NoSQL
深入浅出:使用Node.js构建RESTful API
【10月更文挑战第35天】在数字时代的浪潮中,后端技术如同海洋中稳固的灯塔,为前端应用提供数据和逻辑支撑。本文旨在通过浅显易懂的方式,带领读者了解如何利用Node.js这一强大的后端平台,搭建一个高效、可靠的RESTful API。我们将从基础概念入手,逐步深入到代码实践,最终实现一个简单的API示例。这不仅是对技术的探索,也是对知识传递方式的一次创新尝试。让我们一起启航,探索Node.js的奥秘,解锁后端开发的无限可能。
|
22天前
|
Web App开发 JavaScript 前端开发
构建高效后端服务:Node.js与Express框架的实践
【10月更文挑战第33天】在数字化时代的浪潮中,后端服务的效率和可靠性成为企业竞争的关键。本文将深入探讨如何利用Node.js和Express框架构建高效且易于维护的后端服务。通过实践案例和代码示例,我们将揭示这一组合如何简化开发流程、优化性能,并提升用户体验。无论你是初学者还是有经验的开发者,这篇文章都将为你提供宝贵的见解和实用技巧。
|
24天前
|
Web App开发 JavaScript 中间件
构建高效后端服务:Node.js与Express框架的融合之道
【10月更文挑战第31天】在追求快速、灵活和高效的后端开发领域,Node.js与Express框架的结合如同咖啡遇见了奶油——完美融合。本文将带你探索这一组合如何让后端服务搭建变得既轻松又充满乐趣,同时确保你的应用能够以光速运行。
27 0
|
26天前
|
前端开发 JavaScript
JavaScript新纪元:ES6+特性深度解析与实战应用
【10月更文挑战第29天】本文深入解析ES6+的核心特性,包括箭头函数、模板字符串、解构赋值、Promise、模块化和类等,结合实战应用,展示如何利用这些新特性编写更加高效和优雅的代码。
42 0