运用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天前
|
设计模式 前端开发 JavaScript
【JavaScript 技术专栏】JavaScript 设计模式与实战应用
【4月更文挑战第30天】本文探讨JavaScript设计模式在提升开发效率和代码质量中的关键作用。涵盖单例、工厂、观察者、装饰器和策略模式,并通过实例阐述其在全局状态管理、复杂对象创建、实时数据更新、功能扩展和算法切换的应用。理解并运用这些模式能帮助开发者应对复杂项目,提升前端开发能力。
|
1天前
|
设计模式 JavaScript 算法
js设计模式-策略模式与代理模式的应用
策略模式和代理模式是JavaScript常用设计模式。策略模式通过封装一系列算法,使它们可互换,让算法独立于客户端,提供灵活的选择。例如,定义不同计算策略并用Context类执行。代理模式则为对象提供代理以控制访问,常用于延迟加载或权限控制。如创建RealSubject和Proxy类,Proxy在调用RealSubject方法前可执行额外操作。这两种模式在复杂业务逻辑中发挥重要作用,根据需求选择合适模式解决问题。
|
1天前
|
存储 JavaScript 前端开发
使用Vue.js构建交互式前端的技术探索
【5月更文挑战第12天】Vue.js是渐进式前端框架,以其简洁和强大的特性深受开发者喜爱。它聚焦视图层,采用MVVM模式实现数据与视图的双向绑定,简化开发。核心特性包括响应式数据绑定、组件化、模板系统和虚拟DOM。通过创建Vue实例、编写模板及定义方法,可以构建交互式前端,如计数器应用。Vue.js让复杂、交互式的前端开发变得更加高效和易维护。
|
1天前
|
存储 监控 JavaScript
使用Node.js构建实时聊天应用的技术指南
【5月更文挑战第12天】本文指导使用Node.js、Express.js和Socket.IO构建实时聊天应用。技术栈包括Node.js作为服务器环境、WebSocket协议、Express.js作为Web框架和Socket.IO处理实时通信。步骤包括项目初始化、安装依赖、搭建服务器、实现实时聊天功能、运行应用以及后续的完善和部署建议。通过这个指南,读者可以学习到创建简单实时聊天应用的基本流程。
|
7天前
|
数据采集 JavaScript 数据可视化
Node.js爬虫在租房信息监测与分析中的应用
Node.js爬虫在租房信息监测与分析中的应用
|
13天前
|
开发框架 JavaScript 前端开发
【JavaScript 与 TypeScript 技术专栏】TypeScript 在 Web 开发中的前沿应用
【4月更文挑战第30天】TypeScript在Web开发中日益重要,以其强大的类型系统提升代码质量,支持组件化开发,与React、Vue、Angular等框架良好集成。在大型项目管理中,TypeScript助于代码组织和优化,提高团队协作效率。此外,它提升开发体验,提供智能提示和错误检测。众多成功案例证明其前沿应用,未来将在Web开发领域持续发挥关键作用。
|
13天前
|
前端开发 JavaScript 网络协议
【JavaScript技术专栏】WebSockets在JavaScript中的应用
【4月更文挑战第30天】WebSocket是为解决HTTP协议在实时通信上的局限而诞生的技术,提供全双工、持久连接的通信方式,适合在线聊天、实时游戏等场景。JavaScript中的WebSocket API使浏览器与服务器能建立持久连接,通过事件处理连接、发送/接收数据及错误。相较于AJAX轮询和长轮询,WebSockets更高效、实时,是现代Web实时通信的优选。
|
13天前
|
移动开发 JavaScript 前端开发
【JavaScript技术专栏】Web Worker在JavaScript中的应用
【4月更文挑战第30天】HTML5的Web Worker API解决了JavaScript单线程性能瓶颈问题,允许在后台线程运行JS代码。本文介绍了Web Worker的基本概念、类型、用法和应用场景,如复杂计算、图像处理和数据同步。通过实例展示了搜索建议、游戏开发和实时数据分析等应用,并提醒注意其无法直接访问DOM、需消息传递通信以及移动端资源管理。Web Worker为前端开发提供了多线程能力,提升了Web应用性能和用户体验。
|
13天前
|
JavaScript 前端开发 API
如何利用JavaScript和Electron构建具有丰富功能的桌面应用
【4月更文挑战第30天】如何利用JavaScript和Electron构建具有丰富功能的桌面应用
5 0
|
Web App开发 前端开发 JavaScript
如何用JavaScript判断前端应用运行环境(移动平台还是桌面环境)
如何用JavaScript判断前端应用运行环境(移动平台还是桌面环境)
358 0
如何用JavaScript判断前端应用运行环境(移动平台还是桌面环境)