实现主页面的功能之后,接下来实现分类页面。分类页面中显示一种菜肴类别的详细信息,包括类别名称、图片、描述信息以及属于该类别的一些菜肴。在pages文件夹中添加一个名为classDetail的文件夹,并在classDetail文件夹中添加一个"页面控制"项,将其命名为classDetail,与主页面一样,添加完成之后会默认生成classDetail.html、classDetail.js和classDetail.css这三个文件。
打开classDetail.html文件,在body元素中添加一个div元素,并在div元素内部添加一个button元素、一个h1元素和一个ListView控件,其中button元素是回退按钮,h1元素用于显示菜肴的类别,而ListView控件则用于显示某一类别的菜肴信息。接着再在body元素中添加两个Template控件,分别用来格式化显示类别信息和某一类别中的菜肴。在用于显示类别信息的Template控件中添加一个img控件和一个h4元素,分别用来显示菜肴类别图片和菜肴类别的描述信息;在用于显示某一类菜肴的Template控件中添加一个img控件和两个h4元素,分别用来显示菜肴的图片和描述信息,相关代码如下所示:
<div class="classDetail fragment">
<header aria-label="Header content" role="banner">
<!--定义后退按钮-->
<button class="win-backbutton" aria-label="Back" ></button>
<h1 class="titlearea win-type-ellipsis">
<!--显示类别名称-->
<span class="pagetitle"></span>
</h1>
</header>
<section role="main">
<!--定义ListView控件,用于显示显示类别信息和菜肴-->
<div class="itemslist" data-win-control="WinJS.UI.ListView" data-win-options="{ selectionMode: 'none' }"></div>
</section>
</div>
<!--用于显示类别信息的模板-->
<div class="headerTemplate" data-win-control="WinJS.Binding.Template">
<!--将src属性与数据源中的backgroundImage字段相绑定,将alt属性与数据源中类别名称title 字段绑定-->
<img class="group-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
<!--有关类别的描述信息-->
<h4 class="group-description" data-win-bind="textContent: description"></h4>
</div>
<!--用于显示菜肴的模板-->
<div class="itemTemplate" data-win-control="WinJS.Binding.Template">
<!--将src属性与数据源中的backgroundImage字段相绑定,将alt属性与数据源中菜肴名称title 字段绑定-->
<img class="item-image" src="#" data-win-bind="src: backgroundImage; alt: title" />
<div class="item-info">
<!--菜肴的名称-->
<h4 class="item-title" data-win-bind="textContent: title"></h4>
<!--菜肴的描述信息-->
<h4 class="item-description" data-win-bind="textContent: description"></h4>
</div>
</div>
</body>
为了控制类别信息和菜肴的显示外观,在classDetail.css文件中设置相应的外观属性,相关代码如下所示:
/*设置ListView控件的水平显示位置*/
.classDetail .itemslist .win-horizontal.win-viewport .win-surface {
margin-left: 120px;
margin-bottom: 20px;
}
/*设置ListView控件的大小等*/
.classDetail .itemslist {
position: relative;
height: 100%;
100%;
z-index: 0;
}
/* 设置类别信息的布局、所占据的空间和边距等*/
.classDetail .itemslist .win-groupheader {
-ms-grid-columns: 1fr;
-ms-grid-rows: auto auto 1fr;
display: -ms-grid;
height: 100%;
480px;
margin-left: 0px;
margin-right: 68px;
padding: 0;
}
/* 进一步设置图片的位置、大小和边距*/
.classDetail .itemslist .win-groupheader .group-image {
-ms-grid-row: 2;
height: 238px;
480px;
margin: 0;
margin-bottom: 20px;
}
/* 进一步设置描述信息的位置和边距等*/
.classDetail .itemslist .win-groupheader .group-description {
-ms-grid-row: 3;
margin-bottom: 55px;
overflow: hidden;
}
/* 设置菜肴的布局,以及所占据的空间*/
.classDetail .itemslist .win-item {
-ms-grid-columns: 110px 1fr;
-ms-grid-rows: 1fr;
display: -ms-grid;
height: 110px;
472px;
}
.classDetail .itemslist .win-item .item-info {
-ms-grid-column: 2;
margin-left: 10px;
}
/* 进一步设置菜肴名称的边距,以及所占据的空间等*/
.classDetail .itemslist .win-item .item-info .item-title {
margin-top: 4px;
max-height: 20px;
overflow: hidden;
}
/* 进一步设置描述信息所占据的空间*/
.classDetail .itemslist .win-item .item-info .item-description {
max-height: 60px;
overflow: hidden;
}
/* 设置列表项的背景色和边距等*/
.classDetail .itemslist .win-container {
/*背景设置成透明色*/
background-color: rgba(0, 0, 0, 0);
margin-bottom: 15px;
margin-right: 60px;
padding: 7px;
}
定义了前台页面样式之后,打开classDetail.js文件,在ready函数内添加功能代码,实现将ListView控件与数据源相绑定,以便能够显示数据,并引用模板来控制数据的显示格式,相关代码如下所示:
ready: function (element, options) {
//根据传递的参数来获取某个类别以及该类别中的所有菜肴。如果没有传递参数,则获取第一个类别和该类别中的菜肴
var group = (options && options.groupKey) ? menuData.resolveGroupReference(options.groupKey) : menuData.groups.getAt(0);
//获取该类别中的所有菜肴
this.items = menuData.getItemsFromGroup(group);
//分组菜肴并加入列表
var pageList = this.items.createGrouped(
function groupKeySelector(item) { return group.key; },
function groupDataSelector(item) { return group; }
);
//设置类别名称
element.querySelector(".pagetitle").textContent = group.title;
//获取页面中的ListView控件
var listView = element.querySelector(".itemslist").winControl;
//为类别信息和菜肴设置数据源
listView.groupDataSource = pageList.groups.dataSource;
listView.itemDataSource = pageList.dataSource;
//为类别信息设定模板,按照模板的格式显示数据
listView.groupHeaderTemplate = element.querySelector(".headerTemplate");
//为菜肴设定模板
listView.itemTemplate = element.querySelector(".itemTemplate");
//将ListView控件的布局设置成网格布局
listView.layout = new WinJS.UI.GridLayout({ groupHeaderPosition: "left" });
//给oniteminvoked事件设置处理函数
listView.oniteminvoked = this.ItemInGroupPage_Click.bind(this);
}
上面代码中,在ready函数里对options和options.groupKey进行判断,当参数options和options.groupKey不为空时,调用menuData命名空间下的resolveGroupReference函数根据参数groupKey获取该分类并赋值给变量group;否则获取第一个分类并赋值给变量group。然后调用getItemsFromGroup函数根据变量group来获取指定类别中的所有菜肴并赋值给items变量,使用items的createGrouped函数按照key和group属性值对菜肴进行分组,并把分组的结果赋值给pageList对象。接下来调用element.querySelector函数获取class属性为"pagetitle"的h1元素,将其textContent属性值设置为group.title来显示分类的标题,并通过element.querySelector函数获取class属性值为" itemslist"的ListView控件,将其赋值给listView对象。
然后将pageList对象的groups.dataSource和dataSource两个数据源分别赋值给listView对象的groupDataSource和itemDataSource属性,调用element.querySelector函数获取class属性值为"headerTemplate"和"itemTemplate"的两个Template控件,并分别赋值给listView对象的groupHeaderTemplate和itemTemplate属性。接着通过listView对象的layout属性设置ListView控件的显示布局,并为listView对象的oniteminvoked事件注册事件处理函数ItemInGroupPage_Click。
接着在ready函数后面定义事件处理函数ItemInGroupPage_Click,相关代码如下所示:
ItemInGroupPage_Click: function (args) {
var item = this.items.getAt(args.detail.itemIndex);
WinJS.Navigation.navigate("/pages/foodDetail/foodDetail.html", { item: menuData.getItemReference(item) });
}
在ItemInGroupPage_Click处理函数内,调用items的getAt函数来获取某项菜肴的索引并赋值给变量item,并通过WinJS.Navigation.navigate函数根据菜肴页面的地址和菜肴标识导航到相应的菜肴详细信息页面。
启动调试,当在主页页面上单击某个类别名称时,如"蔬菜类",会跳转到这个类别的详细介绍页面,同时还会显示属于这个类别的一些菜肴,如拌黄瓜、红烧冬瓜和蒜香茄子等,得到的效果如图19-35所示:
图19-35 蔬菜类页面的效果