操作实例:创建博客阅读器(JavaScript 和 HTML)

开发 前端
此操作实例指导你如何使用拆分应用 Visual Studio 模板来创建博客阅读应用。

此操作实例指导你如何使用拆分应用 Visual Studio 模板来创建博客阅读应用。

 

Important  此操作实例适用于 Microsoft Visual Studio 2012 和 Windows 8。 部分内容在 Microsoft Visual Studio 2013 Preview 和 Windows 8.1 Preview 中可能无法正常运行。

了解操作方法:

  • 定义自己的 JSON 数据
  • 使用 Windows.JS.xhr 检索 RSS 数据
  • 使用 PageControl 对象
  • ListView 中显示数据
  • 使用 AppBar 响应命令

WindowsBlogReader

在本教程中,我们为某些 Windows 团队博客创建了一个基本的阅读器。完成后的应用外观如下所示:

Windows 博客阅读器应用的主页、拆分页以及详细信息页。

该项页面题为 "Windows 团队博客",并包含一个 ListView 控件(每个博客一项)。当在 ListView 中单击某项时,可以导航到所选博客的拆分页。该拆分页包含一个 ListView 控件(每篇博客文章一项),同时还包含一个控件用于纵向显示当前所选的博客文章的内容。从拆分页可以导航到项目详细信息页面,在详细信息页面中,博客文章的标题显示在顶部,当前所选博客文章的内容以水平方式显示。

在 Visual Studio 中创建新项目

为我们的应用创建一个名为 WindowsBlogReader 的新项目。以下是操作方法:

  1. 启动 Visual Studio。
  2. 在“起始页”选项卡中,单击“新建项目”。随即将打开“新建项目”对话框。
  3. 在“已安装”窗格中,展开 JavaScript 并选择“Windows 应用商店应用”模板类型。JavaScript 可用的项目模板随即将显示在对话框的中心窗格中。
  4. 在中心窗格中,选择“拆分应用”项目模板。
  5. 在“名称”文本框中,输入 "WindowsBlogReader"。
  6. 单击“确定”以创建项目。这需要花费一点时间。

下面是在解决方案资源管理器中显示的项目的结构。页面文件夹包含两组文件,一组文件用于项页面,另一组文件用于拆分页面。这些组中的每个组为 PageControl、一组 HTML、CSS 以及 JavaScript 文件,这些文件定义应用可以导航至或用作自定义控件的页面。

新项目包含创建项 PageControl 和拆分 PageControl 所需的 HTML、CSS 和 JavaScript 文件。稍后我们将为项详细信息 PageControl 添加文件。

解决方案资源管理器中 WindowsBlogReader 项目的屏幕截图。

启动我们的新 Windows 应用商店应用

如果你非常想看到基本的分隔应用的外观,请按 F5 以生成、部署并启动应用。应用显示为全屏页面,标题为 "WindowsBlogReader",包含一列示例项目,显示为网格。每个项目表示一组数据。点击或单击列表中的项目以导航至拆分页。拆分页包含两个 核心内容区域。在左侧,你可以看到与所选组关联的项目列表。在右侧,可以看到所选项目的内容。可以通过点击或单击页面上的“后退”按钮来返回项目页。

运行应用时,应用会提取 items.html 中的(或其中链接的)HTML、CSS 和 JavaScript,并将其注入到作为应用起始页的 default.html 页面中。对于在应用容器中运行的代码默认可以执行的操作有一些限制。例如,你的应用不能访问 Internet 或摄像头,除非你声明应用需要此访问权限,且用户在安装应用时授予了此访问权限。如需了解详细信息,请打开 package.appxmanifest,并转至“许可范围”选项卡。

更改标题和背景色

我们来执行两个简单的任务来自定义应用。

若要更改应用标题,请打开 items.html,然后将 itemspage 中的 h1 元素文本替换为 "Windows 团队博客",如此处所示。

  1. <h1 class="titlearea win-type-ellipsis"> 
  2.     <span class="pagetitle">Windows Team Blogs</span> 
  3. </h1> 

若要设置应用的背景色,请打开 default.css,并将此 background-color 属性添加到 #contenthost 中。

  1. #contenthost { 
  2.     height100%
  3.     width100%;     
  4.     background-color#0A2562

 

按 F5 来生成、部署并启动此应用。请注意,项目页的标题已更改,项目页和拆分页的背景色为蓝色。

Note项目中的 images 文件夹包含默认的文件,系统将这些文件用于应用启动时应用的磁贴和初始屏幕。在本教程中,我们不更改这些内容,但是你可以按照自己的喜好使用其他图像。只 需将要使用的图像文件添加到 images 文件夹中即可。打开 package.appxmanifest,将“应用程序 UI”选项卡上“徽标”、“小徽标”和“初始屏幕”的内容替换为你的图像文件的路径。

#p#

替换示例数据

项目模板包含运行应用时看到的示例数据。我们使用这些步骤为 Windows 团队博客将这些示例数据替换为来自 ATOM 源的数据:

删除示例数据

打开 data.js,其中包含应用的示例数据。

我们不需要 generateSampleData 函数,因此你可以将它删除。

  1. // Returns an array of sample data that can be added to the application's 
  2. // data list.  
  3. function generateSampleData() { 
  4.     // Omitted code. 
  5.  
  6.          

我们不需要此代码,所以你可以将其删除:

  1. // TODO: Replace the data with your real data. 
  2. // You can add data from asynchronous sources whenever it becomes available. 
  3. generateSampleData().forEach(function (item) { 
  4.     list.push(item); 
  5. }); 

设置变量和函数

将此代码添加到 data.js(文件开头的 var list = new WinJS.Binding.List(); 声明前面)。此代码可设置我们所需的变量以及填充它们的函数。在执行本教程中的步骤时,你可以利用其中包含的注释来找到每一步放置代码的位置。

  1. // Set up array variables 
  2.  
  3. var dataPromises = []; 
  4. var blogs; 
  5.  
  6. // Create a data binding for our ListView 
  7.  
  8. var blogPosts = new WinJS.Binding.List(); 
  9.  
  10. // Process the blog feeds 
  11.  
  12. function getFeeds() {  
  13.     // Create an object for each feed in the blogs array 
  14.     // Get the content for each feed in the blogs array 
  15.     // Return when all asynchronous operations are complete 
  16.  
  17. function acquireSyndication(url) { 
  18.     // Call xhr for the URL to get results asynchronously 
  19.  
  20. function getBlogPosts() { 
  21.     // Walk the results to retrieve the blog posts 
  22.  
  23. function getItemsFromXml(articleSyndication, bPosts, feed) { 
  24.     // Get the info for each blog post 

定义博客列表

为了使这个示例简单一点,我们在 blogs 数组中包含一列硬编码的 URL。

将此代码添加到 getFeeds 函数。此代码将 JSON 数组添加到 blogs 数组。每个 JSON 数组都包含多个 JSON 对象,以存储来自源的内容。JSON 对象是名称/值对的未经排序的容器。例如,博客标题存储在一个 JSON 对象中,该对象名为 title,还有一个从 ATOM 源检索的值。使用 JSON 对象使我们将来自源的内容绑定到应用的控件变得很简单。

  1. // Create an object for each feed in the blogs array 
  2. blogs = [ 
  3.     key: "blog1"
  4.     url: 'http://blogs.windows.com/skydrive/b/skydrive/atom.aspx'
  5.     title: 'tbd', updated: 'tbd'
  6.     acquireSyndication: acquireSyndication, dataPromise: null 
  7. }, 
  8.     key: "blog2"
  9.     url: 'http://blogs.windows.com/windows/b/windowsexperience/atom.aspx'
  10.     title: 'tbd', updated: 'tbd'
  11.     acquireSyndication: acquireSyndication, dataPromise: null 
  12. }, 
  13.     key: "blog3"
  14.     url: 'http://blogs.windows.com/windows/b/extremewindows/atom.aspx'
  15.     title: 'tbd', updated: 'tbd'
  16.     acquireSyndication: acquireSyndication, dataPromise: null 
  17. }, 
  18.     key: "blog4"
  19.     url: 'http://blogs.windows.com/windows/b/business/atom.aspx'
  20.     title: 'tbd', updated: 'tbd'
  21.     acquireSyndication: acquireSyndication, dataPromise: null 
  22. }, 
  23.     key: "blog5"
  24.     url: 'http://blogs.windows.com/windows/b/bloggingwindows/atom.aspx'
  25.     title: 'tbd', updated: 'tbd'
  26.     acquireSyndication: acquireSyndication, dataPromise: null 
  27. }, 
  28.     key: "blog6"
  29.     url: 'http://blogs.windows.com/windows/b/windowssecurity/atom.aspx'
  30.     title: 'tbd', updated: 'tbd'
  31.     acquireSyndication: acquireSyndication, dataPromise: null 
  32. }, 
  33.     key: "blog7"
  34.     url: 'http://blogs.windows.com/windows/b/springboard/atom.aspx'
  35.     title: 'tbd', updated: 'tbd'
  36.     acquireSyndication: acquireSyndication, dataPromise: null 
  37. }, 
  38.     key: "blog8"
  39.     url: 'http://blogs.windows.com/windows/b/windowshomeserver/atom.aspx'
  40.     title: 'tbd', updated: 'tbd'
  41.     acquireSyndication: acquireSyndication, dataPromise: null 
  42. }, 
  43.     key: "blog9"
  44.     url: 'http://blogs.windows.com/windows_live/b/developer/atom.aspx'
  45.     title: 'tbd', updated: 'tbd'
  46.     acquireSyndication: acquireSyndication, dataPromise: null 
  47. }, 
  48.     key: "blog10"
  49.     url: 'http://blogs.windows.com/ie/b/ie/atom.aspx'
  50.     title: 'tbd', updated: 'tbd'
  51.     acquireSyndication: acquireSyndication, dataPromise: null 
  52. }, 
  53.     key: "blog11"
  54.     url: 'http://blogs.windows.com/windows_phone/b/wpdev/atom.aspx'
  55.     title: 'tbd', updated: 'tbd'
  56.     acquireSyndication: acquireSyndication, dataPromise: null 
  57. }, 
  58.     key: "blog12"
  59.     url: 'http://blogs.windows.com/windows_phone/b/wmdev/atom.aspx'
  60.     title: 'tbd', updated: 'tbd'
  61.     acquireSyndication: acquireSyndication, dataPromise: null 
  62. }]; 

#p#

检索源数据

对于此部分中的步骤,我们使用适用于 JavaScript 的 Windows 库来管理联合源。

将此代码添加到 acquireSyndication 函数。我们调用 Windows.JS.xhr 函数以检索源内容。此调用为异步调用。幸运的是,程序已经为我们处理好了在进行异步调用时可能会遇到的许多复杂问题。xhr 返回时,我们将收到结果的承诺,此承诺将返回到调用方。

  1. // Call xhr for the URL to get results asynchronously 
  2. return WinJS.xhr( 
  3.     { 
  4.         url: url, 
  5.         headers: { "If-Modified-Since""Mon, 27 Mar 1972 00:00:00 GMT" } 
  6.                  
  7.     }); 

现在,我们将代码添加到 getFeeds 函数以调用 blogs 数组中每个博客的 acquireSyndication 函数,并添加返回到我们 promise 数组的 promise dataPromises。我们先调用 WinJS.Promise.join 函数,等待所有承诺均已满足后,再从 getFeeds 返回。这可以确保在显示 ListView 控件之前,我们拥有全部所需的信息。

  1. // Get the content for each feed in the blogs array 
  2. blogs.forEach(function (feed) { 
  3.     feed.dataPromise = feed.acquireSyndication(feed.url); 
  4.     dataPromises.push(feed.dataPromise); 
  5. }); 
  6.  
  7. // Return when all asynchronous operations are complete 
  8. return WinJS.Promise.join(dataPromises).then(function () { 
  9.     return blogs; 
  10. }); 

接下来,将此代码添加到 getBlogPosts 函数。对于 blogs 数组中的每个博客,我们针对所需的信息分析 XML 源数据。首先,我们使用 responseXML 属性以获得响应正文,然后使用 querySelector 方法以及所需的选择器来获得博客的标题和最后更新日期。我们使用 Windows.Globalization.DateTimeFormatting.DateTimeFormatter 来转换显示的上次更新日期。

如果 articlesResponse.responseXMLnull,则说明加载博客时出错,因此我们会在博客发布位置显示一条错误消息。

  1. // Walk the results to retrieve the blog posts 
  2. getFeeds().then(function () { 
  3.     // Process each blog 
  4.     blogs.forEach(function (feed) { 
  5.         feed.dataPromise.then(function (articlesResponse) { 
  6.  
  7.             var articleSyndication = articlesResponse.responseXML; 
  8.  
  9.             if (articleSyndication) { 
  10.                 // Get the blog title  
  11.                 feed.title = articleSyndication.querySelector("feed > title").textContent; 
  12.  
  13.                 // Use the date of the latest post as the last updated date 
  14.                 var published = articleSyndication.querySelector("feed > entry > published").textContent; 
  15.  
  16.                 // Convert the date for display 
  17.                 var date = new Date(published); 
  18.                 var dateFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter( 
  19.                     "month.abbreviated day year.full"); 
  20.                 var blogDate = dateFmt.format(date); 
  21.                 feed.updated = "Last updated " + blogDate; 
  22.  
  23.                 // Get the blog posts 
  24.                 getItemsFromXml(articleSyndication, blogPosts, feed); 
  25.             } 
  26.             else { 
  27.                          
  28.                 // There was an error loading the blog.  
  29.                 feed.title = "Error loading blog"
  30.                 feed.updated = "Error";  
  31.                 blogPosts.push({ 
  32.                     group: feed, 
  33.                     key: "Error loading blog"
  34.                     title: feed.url, 
  35.                     author: "Unknown"
  36.                     month: "?"
  37.                     day: "?"
  38.                     year: "?"
  39.                     content: "Unable to load the blog at " + feed.url 
  40.                 }); 
  41.  
  42.             } 
  43.         }); 
  44.     }); 
  45. }); 
  46.  
  47. return blogPosts; 

最后,将此代码添加到 getItemsFromXml 函数。首先,我们使用 querySelectorAll 来获得博客文章集以及每篇博客文章的信息。然后,我们使用 querySelector 来获得每篇博客文章的信息。我们使用 Windows.Globalization.DateTimeFormatting.DateTimeFormatter 来转换显示的上次更新日期。最后,我们使用 push 方法将每篇博客文章的信息存储在 bPosts 数组中的相应条目中。

  1. // Get the info for each blog post 
  2. var posts = articleSyndication.querySelectorAll("entry"); 
  3.  
  4. // Process each blog post 
  5. for (var postIndex = 0; postIndex < posts.length; postIndex++) { 
  6.     var post = posts[postIndex]; 
  7.  
  8.     // Get the title, author, and date published 
  9.     var postTitle = post.querySelector("title").textContent; 
  10.     var postAuthor = post.querySelector("author > name").textContent; 
  11.     var postPublished = post.querySelector("published").textContent; 
  12.  
  13.     // Convert the date for display 
  14.     var postDate = new Date(postPublished); 
  15.     var monthFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter( 
  16.         "month.abbreviated"); 
  17.     var dayFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter( 
  18.         "day"); 
  19.     var yearFmt = new Windows.Globalization.DateTimeFormatting.DateTimeFormatter( 
  20.         "year.full"); 
  21.     var blogPostMonth = monthFmt.format(postDate); 
  22.     var blogPostDay = dayFmt.format(postDate); 
  23.     var blogPostYear = yearFmt.format(postDate); 
  24.  
  25.     // Process the content so it displays nicely 
  26.     var staticContent = toStaticHTML(post.querySelector("content").textContent); 
  27.  
  28.     // Store the post info we care about in the array 
  29.     bPosts.push({ 
  30.         group: feed, 
  31.         key: feed.title, 
  32.         title: postTitle, 
  33.         author: postAuthor, 
  34.         month: blogPostMonth.toUpperCase(), 
  35.         day: blogPostDay, 
  36.         year: blogPostYear, 
  37.         content: staticContent 
  38.     });                                          

#p#

使数据可用

现在,我们已完成了将源数据存储到数组中的代码,我们需要按照 ListView 控件的预期来对源数据进行分组。我们还需要完成将源数据绑定到 ListView 控件这一任务。

getItemsFromGroup 函数调用 createFiltered 方法,并返回指定博客的博客文章。getItemsFromGroup 函数依赖变量 list

  1. var list = new WinJS.Binding.List(); 

将此定义替换为对 getBlogPosts 函数的调用,该函数返回 blogPosts 变量。这是一个 WinJS.Binding.List 对象。

  1. var list = getBlogPosts(); 

注意,调用 createGrouped 方法将按指定的键(此情况中是指每篇文章所属的博客)对博客文章排序。

  1. var groupedItems = list.createGrouped( 
  2.     function groupKeySelector(item) { return item.group.key; }; 
  3.     function groupDataSelector(item) { return item.group; } 

更新项 PageControl

PageControl 的主要功能是使用 WinJS.UI.ListView 实现的 ListView 控件。每个博客在此列表中都有一个项目。让我们修改模板中提供的 ListView 项,以包含博客标题和上次更新博客的日期。

打开 items.html。我们需要更新此 div 标记中的 HTML,从而在我们的 blogs 数组中反映内容。

  1. <div class="itemtemplate" data-win-control="WinJS.Binding.Template"> 
  2.     <div class="item"> 
  3.         <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" /> 
  4.         <div class="item-overlay"> 
  5.             <h4 class="item-title" data-win-bind="textContent: title"></h4> 
  6.             <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6> 
  7.         </div> 
  8.     </div> 
  9. </div> 

进行以下更新:

  1. 因为不是每个博客都有图像,因此请删除 img 标记。
  2. h6 标记中,将 textContent: subtitle 更新为 textContent: updated。这会在 ListView 项目的覆盖部分中放置上次更新日期。
  3. 移动位于类 item-overlaydiv 之前的 h4 标记。这会在 ListView 项目的主要部分中放置博客标题。

结果如下所示。

  1. <div class="itemtemplate" data-win-control="WinJS.Binding.Template"> 
  2.     <div class="item"> 
  3.         <h4 class="item-title" data-win-bind="textContent: title"></h4> 
  4.         <div class="item-overlay">            
  5.             <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: updated"></h6> 
  6.         </div> 
  7.     </div> 
  8. </div> 

若要将列表项目的颜色设置为浅蓝色,请打开 items.css 并添加此处所示的 background-color 属性。此外,在 -ms-grid-rows 属性中将第二行的大小从 90px 更改为 60px,如此处所示,因为我们只显示覆盖中的上次更新日期。

  1. .itemspage .itemslist .item { 
  2.     -ms-grid-columns: 1fr; 
  3.     -ms-grid-rows: 1fr 60px
  4.     display: -ms-grid; 
  5.     height250px
  6.     width250px
  7.     background-color#557EB9

若要为博客标题设置字体大小和边距,请将此代码添加到 items.css。

  1. .itemspage .itemslist .win-item .item-title { 
  2.     -ms-grid-row: 1
  3.     overflowhidden
  4.     width220px
  5.     font-size:  24px
  6.     margin-top12px
  7.     margin-left15px

更新拆分 PageControl

打开 split.html。模板中拆分页的 HTML 使用与示例数据相同的名称。我们需要更新此 div 标记中的 HTML,从而在我们的 blogPosts 数组中反映名称。

  1. <div class="itemtemplate" data-win-control="WinJS.Binding.Template"> 
  2.     <div class="item"> 
  3.         <img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" /> 
  4.         <div class="item-info"> 
  5.             <h3 class="item-title win-type-ellipsis" data-win-bind="textContent: title"></h3> 
  6.             <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: subtitle"></h6> 
  7.             <h4 class="item-description" data-win-bind="textContent: description"></h4> 
  8.         </div> 
  9.     </div> 
  10. </div> 

进行以下更新:

  1. 将 img 标记替换为新的 <div class="item-date">...</div> 节点。
  2. 在 h6 标记中,将 textContent: subtitle 改为 textContent: author。
  3. 删除 h4 标记

结果如下所示。

  1. <div class="itemtemplate" data-win-control="WinJS.Binding.Template"> 
  2.     <div class="item"> 
  3.        <div class="item-date"> 
  4.           <p class="item-month" data-win-bind="innerHTML: month"></p> 
  5.           <span class="item-day" data-win-bind="innerHTML: day"></span> |  
  6.           <span class="item-year" data-win-bind="innerHTML: year"></span> 
  7.        </div> 
  8.         <div class="item-info"> 
  9.             <h3 class="item-title win-type-ellipsis" data-win-bind="textContent: title"></h3> 
  10.             <h6 class="item-subtitle win-type-ellipsis" data-win-bind="textContent: author"></h6> 
  11.         </div> 
  12.     </div> 
  13. </div> 

注意,我们将管道字符用作分隔符,因为 HTML 不包含用于绘制竖线的标记。

因为我们没有包含在示例数据中的所有信息,所以从 articleSection 删除此代码可以简化页面。

  1. <header class="header"> 
  2.     <div class="text"> 
  3.         <h2 class="article-title win-type-ellipsis" data-win-bind="textContent: title"></h2> 
  4.         <h4 class="article-subtitle" data-win-bind="textContent: subtitle"></h4> 
  5.     </div> 
  6.     <img class="article-image" src="#" data-win-bind="src: backgroundImage; alt: title" /> 
  7. </header> 

#p#

若要设置文本块的颜色以及文本的项目日期、字体和边距,请打开 split.css 并添加此代码。

  1. .splitpage .itemlistsection .itemlist .item .item-date { 
  2.     -ms-grid-column:  1
  3.     background-color#557EB9
  4.  
  5.     .splitpage .itemlistsection .itemlist .item .item-date .item-month{ 
  6.         margin-top12px
  7.         margin-left12px
  8.         margin-bottom4px
  9.         font-weightbold
  10.         font-size28px
  11.     } 
  12.  
  13.     .splitpage .itemlistsection .itemlist .item .item-date .item-day{ 
  14.         margin-left12px
  15.         font-size28px
  16.     } 

若要获取我们所需的页面布局,请将此 -ms-grid-row 属性从 "1" 改为 "2"。这导致页面标题填满整个第一行,并且将 ListView 和文章放在第二行。

  1. .splitpage .articlesection { 
  2.     -ms-grid-column: 2
  3.     -ms-grid-row: 2
  4.     -ms-grid-row-span: 2
  5.     margin-left50px
  6.     overflow-y: auto
  7.     padding-right120px
  8.     positionrelative
  9.     z-index0

现在,来试试再次运行应用吧。按 F5 可构建、部署并启动此应用。可以立即看到页面标题,但是应用检索源数据时有短暂的延迟。满足所有承诺后,可以看到在 ListView 中每个博客一个项。(此代码以满足承诺的顺序将这些项添加到 ListView 中。)点击或单击 ListView 中的项会将你带到拆分页,此拆分页包含所选博客的博客文章列表以及所选博客文章的内容。默认选中第一篇博客文章。

单击“后退”箭头可返回到项页。请注意,返回到屏幕的磁贴带有过渡动画。这是 Windows JavaScript 库中的一个功能,它支持控件以及其他用户界面元素按照 Windows 应用商店应用的 UX 指南移动。

横向方向主页的屏幕截图。

添加项详细信息 PageControl

项详细信息 PageControl 将博客文章的标题显示为自己的标题,并有一块区域包含博客文章的内容。

添加项详细信息 PageControl 的步骤:

  1. 在解决方案资源管理器中,右键单击 pages 文件夹,选择“添加”>“新建文件夹”。
  2. 将该文件夹命名为 itemDetail。
  3. 在解决方案资源管理器中,右键单击 itemDetail 文件夹,选择“添加”>“新建项”。
  4. 选择“JavaScript”>“Windows 应用商店”>“页面控件”,然后使用文件名 itemDetail.html。
  5. 单击“添加”以在 pages/itemDetail 文件夹中创建 itemDetail.css、itemDetail.html 和 itemDetail.js 文件。

打开 itemDetail.html 并更新此处所示的主要部分。此代码定义页面布局。(这是网格应用模板中包含的 itemDetail.html 页面代码的简化版本。)

  1. <!DOCTYPE html> 
  2. <html> 
  3. <head> 
  4.     <meta charset="utf-8" /> 
  5.     <title>itemDetail</title> 
  6.  
  7.     <!-- WinJS references --> 
  8.     <link href="//Microsoft.WinJS.2.0.Preview/css/ui-dark.css" rel="stylesheet" /> 
  9.     <script src="//Microsoft.WinJS.2.0.Preview/js/base.js"></script> 
  10.     <script src="//Microsoft.WinJS.2.0.Preview/js/ui.js"></script> 
  11.  
  12.     <link href="itemDetail.css" rel="stylesheet" /> 
  13.     <script src="itemDetail.js"></script> 
  14. </head> 
  15. <body> 
  16.     <div class="itemDetail fragment"> 
  17.         <header aria-label="Header content" role="banner"> 
  18.             <button class="win-backbutton" aria-label="Back" disabled type="button"></button> 
  19.             <h1 class="titlearea win-type-ellipsis"> 
  20.                 <span class="pagetitle">Welcome to itemDetail</span> 
  21.             </h1> 
  22.         </header> 
  23.         <section aria-label="Main content" role="main"> 
  24.             <p>Content goes here.</p> 
  25.         </section> 
  26.     </div> 
  27. </body> 
  28. </html> 

用以下代码替换 Main content 部分。

  1. <section aria-label="Main content" role="main"> 
  2.     <article> 
  3.         <div class="item-content"></div> 
  4.     </article> 
  5. </section> 

打开 itemDetail.js 并更新此处所示的 ready 函数的代码。此代码显示用户导航至此页面时的标题和内容。(这是网格应用模板中包含的 itemDetail.js 页面代码的简化版本。)

  1. ready: function (element, options) { 
  2.    // Display the appbar but hide the Full View button 
  3.    var appbar = document.getElementById('appbar'); 
  4.    var appbarCtrl = appbar.winControl; 
  5.    appbarCtrl.hideCommands(["view"], false); 
  6.  
  7.    var item = options && options.item ? options.item : Data.items.getAt(0);                                            
  8.    element.querySelector(".titlearea .pagetitle").textContent = item.title; 
  9.    element.querySelector("article .item-content").innerHTML = item.content; 
  10. }, 

#p#

现在,我们为项详细信息页面定义样式。打开 itemDetail.css,使用此处显示的代码替换模板代码。

  1. .itemDetail section[role=main] { 
  2.     -ms-grid-row: 2
  3.     displayblock
  4.     height100%
  5.     overflow-x: auto
  6.     positionrelative
  7.     width100%
  8.     z-index0
  9.  
  10.     .itemDetail section[role=main] article { 
  11.         /* Define a multi-column, horizontally scrolling article by default. */ 
  12.         column-fill: auto
  13.         column-gap: 80px
  14.         column-width480px
  15.         height: calc(100% - 50px); 
  16.         margin-left120px
  17.         width480px
  18.     } 
  19.  
  20.         .itemDetail section[role=main] article .item-content p { 
  21.             margin-bottom20px
  22.             margin-right20px
  23.             vertical-alignbaseline
  24.         } 
  25.  
  26. @media screen and (-ms-view-state: snapped) { 
  27.     .itemDetail section[role=main] article { 
  28.         /* Define a single column, vertically scrolling article in snapped mode. */ 
  29.         -ms-grid-columns: 300px 1fr; 
  30.         -ms-grid-row: 2
  31.         -ms-grid-rows: auto 60px
  32.         display: -ms-grid; 
  33.         height100%
  34.         margin-left20px
  35.         overflow-x: hidden
  36.         overflow-y: auto
  37.         width300px
  38.     } 
  39.  
  40.         .itemDetail section[role=main] article .item-content { 
  41.             padding-bottom60px
  42.         } 
  43.  
  44. @media screen and (-ms-view-state: fullscreen-portrait) { 
  45.     .itemDetail section[role=main] article { 
  46.         margin-left100px
  47.     } 

添加带有显示项目详细信息页面命令的应用栏

我们添加一个应用栏,它包含可用于导航到项目详细信息页面的按钮,并使此按钮仅在我们位于拆分页时才显示。

打开 default.html 并取消注释此代码。

  1. <!-- <div id="appbar" data-win-control="WinJS.UI.AppBar"> 
  2.     <button data-win-control="WinJS.UI.AppBarCommand" data-win-options="{id:'cmd', label:'Command', icon:'placeholder'}" type="button"></button> 
  3. </div> --> 

修改占位符按钮的定义,以在应用栏靠右侧远端创建一个标签为“完全视图”的按钮,如此处所示。

  1. <div id="appbar" data-win-control="WinJS.UI.AppBar"> 
  2.     <button data-win-control="WinJS.UI.AppBarCommand"  
  3.         data-win-options="{id:'view', label:'Full View', icon:'add'}" type="button"> 
  4.     </button> 
  5. </div>  

在导航至项目页面和项目详细信息页面时,我们不希望“完全视图”按钮显示在应用栏上。将此代码添加到 items.js 中的 ready 函数内以隐藏按钮。(此代码已经出现在我们创建的 ready 中的 itemDetail.js 函数内。)

  1. // Display the appbar but hide the Full View button 
  2. var appbar = document.getElementById('appbar'); 
  3. var appbarCtrl = appbar.winControl; 
  4. appbarCtrl.hideCommands(["view"], false); 

我们导航至拆分页时,“完全视图”按钮将显示在应用栏上。将此代码添加到 split.js 中的 ready 函数内以显示按钮。

  1. // Display the appbar and show the Full View button 
  2. var appbar = document.getElementById('appbar'); 
  3. var appbarCtrl = appbar.winControl; 
  4. appbarCtrl.showCommands(["view"], false); 

从拆分 PageControl 导航到项详细信息 PageControl

用户单击应用栏上的“完全视图”按钮时,应用导航到项详细信息 PageControl 并显示所选博客文章的标题和内容。

打开 split.js。将此变量声明添加到 utils 变量声明的后面。

  1. // The selected item 
  2. var post; 

在第二次调用 querySelector 之前将此语句添加到 ready 函数,以便可以先设置 this.items。此代码将 post 变量设置为用户导航至页面时第一篇博客文章的索引。

  1. // Get the first item, which is the default selection 
  2. post = this._items.getAt(0); 

将此语句添加到 _selectionChanged 函数,该函数位于设置 this._itemSelectionIndex 的语句后面。此代码会将 post 变量设置为用户所选博客文章的索引。

  1. // Get the item selected by the user 
  2. post = this._items.getAt(this._itemSelectionIndex); 

在 _selectionChanged 函数之外,将此事件处理程序函数添加到 post 变量声明的后面。用户单击“完全视图”按钮时即调用此处理程序。WinJS.Navigation.navigate 函数会加载项详细信息页面,并将所选的博客文章作为项传递。

  1. function displayFullView() { 
  2.     // Display the selected item in the item detail page 
  3.     nav.navigate('/pages/itemDetail/itemDetail.html', { item: post }); 

将此代码添加到 ready 函数中(在我们添加的代码的之后),以显示“完全视图”按钮。此代码将我们的 displayFullView 函数注册为“完全视图”按钮的 click 事件的事件处理程序。

  1. // Register the event handler for the Full View button 
  2. document.getElementById('view').addEventListener("click", displayFullView, false); 

#p#

按 F5 以运行应用。单击项目页上的项目会将你带到拆分页,此拆分页包含博客文章列表以及所选博客文章的内容。点击或单击博客文章,文章内容即显示在右侧栏中。若要显示应用栏,请右键单击,或者从底端或顶端轻扫(如果你的系统支持触摸)。

横向方向拆分页的屏幕截图。

点击或单击“完全视图”按钮,我们的应用将在项目详细信息页面中显示所选博客文章的内容。

横向方向详细信息页面的屏幕截图。

如果点击或单击“后退”按钮,则返回到拆分页。ListView 中的第一项被选中,它不一定是你在项目详细信息页面中选择显示的项。 你可以根据需要添加代码来保存并还原所选项。

我们的应用所使用的模板代码可以显示横向和纵向方向。旋转你的电脑,或在 Microsoft Visual Studio Express 2012 for Windows 8 的模拟器中运行你的应用,然后旋转显示器。项页外观如下所示。

纵向方向主页的屏幕截图。

拆分页外观如下所示。请注意,在选择项目前,仅显示 ListView 控件。然后,博客文章以垂直方向显示。如果单击 Full View 按钮,则博客文章以水平方向显示。

纵向方向拆分页的屏幕截图。

摘要

我们已经完成了应用的代码!我们了解了如何构建内置页面模板,如何将数据与 ListView 绑定,如何导航至新页面以及如何添加带按钮的应用栏。

原文链接:http://msdn.microsoft.com/zh-cn/library/windows/apps/hh974582.aspx

 

责任编辑:陈四芳 来源: microsoft.com
相关推荐

2013-09-02 16:59:34

JavaScriptHTML

2013-09-03 11:06:05

Windows

2011-09-15 18:43:00

UbuntuchmPDF

2013-09-02 16:52:31

Windows 8.1

2014-12-03 10:46:15

iReader

2017-04-11 13:31:40

阅读器开源RSS

2009-05-05 09:00:48

RSS浏览器

2011-09-09 10:19:13

2024-05-16 13:44:18

2010-09-30 09:21:39

2014-12-17 15:23:03

Android网络阅读器源码

2015-12-03 10:04:36

Ncurses工具LNAV

2023-09-29 11:47:23

2022-06-02 14:01:54

屏幕阅读器NVDAWindows

2023-03-23 13:47:00

LinuxEPUB阅读器

2016-12-20 09:29:11

AlduinLinuxRSS

2009-08-27 09:19:51

RSS阅读器Web 1.0

2021-05-21 05:26:02

谷歌Chrome 浏览器

2010-01-22 14:20:17

Visual C++

2009-08-25 16:12:46

Visual C#制作
点赞
收藏

51CTO技术栈公众号