本主題提供有關使用 JavaScript 爲 Windows 構建的 Windows 應用商店應用的項目模板的深入信息。除每個模板的簡單摘要外,還提供了有關導航模型、數據模型、視圖狀態處理的實施詳細信息以及其他詳細信息。許多這些實施詳細信息適用於多個模板。
有關其他語言的 Visual Studio 模板和 Blend 模板的信息,請參閱使用模板立即開始你的應用(C#/VB/C++)。
適用於 Windows 應用商店應用的網格項目模板
網格應用模板是開始創建 Windows 應用商店應用的一種非常有用的方法,你可以自定義該模板,以便用戶能夠通過瀏覽不同類別來找到他們所需的內容。例如購物應用、新聞應用、照片或視頻應用。此模板使用爲 Windows 應用商店應用建議的 JavaScript 導航模型。
網格應用默認顯示一個主頁,其中顯示組列表。“組”表示指定的一組項目,比如一個包含各個零售項的虛擬部門商店分部。如果用戶選擇一個組,應用將打開該組的詳細信息頁面,並在該頁右側顯示項列表。用戶可以從主頁或組詳細信息頁面中選擇項。這將打開顯示項詳細信息的整頁視圖(下面是顯示在頂部的頁面)。
“網格”模板的項目文件
網格應用模板包含以下 HTML 文件:
- default.html,該文件最先加載,併爲內容主體(其中每個頁面都加載進主窗口)提供標記。
- groupedItems.html,這是主頁。用戶通過它可以查看組和項,或選擇一個項以導航到整頁項視圖,或選擇一個組標籤以導航到組詳細信息頁面。
- groupDetail.html,允許用戶在左側查看組詳細信息,同時在右側查看項,並選擇一個項以導航到整頁項視圖。
- itemDetail.html,某個項的整頁視圖。
該模板包含以下 JavaScript 文件:
- default.js,指定當啓動應用時應用的行爲。
- groupedItems.js,指定與主頁相關聯的行爲。
- groupDetail.js,指定與組詳細信息頁面相關聯的行爲。
- itemDetail.js,指定與整頁項視圖相關聯的行爲。
- navigator.js,實現適用於 Windows 應用商店應用 JavaScript 模板的導航模型。
- data.js,這是數據源對象,它嚮應用的其餘部分公開數據。
該模板包含以下 CSS 文件:
- default.css,爲內容主體頁面和應用整體指定 CSS 樣式。
- groupedItems.css,爲主頁指定 CSS 樣式。
- groupDetail.css,爲組詳細信息頁面指定 CSS 樣式。
- itemDetail.css,爲整頁項視圖指定 CSS 樣式。
網格應用模板還包含 package.appxmanifest 文件(該文件介紹用於 Windows 的應用包)和 PFX 文件(用於爲 appxmanifest 文件簽名並且此文件作爲項目文件包含以支持從命令行構建)。該模板還包含一些圖像文件,如用作初始屏幕圖像的 splashscreen.png,以及用於 Windows 應用商店的 storelogo.png。
“網格”模板的工作原理
常見的編碼功能
下列功能對所有項目模板都通用:
- 每個 JavaScript 文件都將代碼包裝在自我執行匿名函數中,如下所示:
JavaScript
(function () {
// . . .
})();
在匿名函數內部添加的成員是專用的,但你可使用 WinJS.Namespace.define函數將其公開。使用匿名函數會更改編寫某些代碼(例如當你添加自己的事件處理程序時)所需的方式。有關詳細信息,請參閱對基本應用編碼。
- 各 JavaScript 文件使用“use strict”語句指定使用嚴格模式。有關詳細信息,請參閱 JavaScript 語言參考中的嚴格模式。
- Default.js 包含對 WinJS.Binding.optimizeBindingReferences 的調用。此函數有助於防止在應用中使用聲明性綁定時出現內存泄漏(模板中常見問題)。
- 嚴格的聲明性處理始終處於打開狀態。你必須使用 WinJS.Utilities.markSupportedForProcessing 來指定函數可以使用聲明性處理。
XML 文檔註釋在 JavaScript 文件中用在幾個地方,用來提供更完整的 IntelliSense 體驗。有關詳細信息,請參閱 JavaScript IntelliSense。
應用生命週期
應用生命週期的實現對於所有適用於 Windows 應用商店應用的JavaScript 項目模板而言都是相同的。應用生命週期在應用啓動時開始,並在應用關閉時結束。項目模板包含一個用於管理應用生命週期的通用模式。當你創建基於項目模板的應用時,可能需要包含用於處理其他情況的代碼,如當應用掛起或終止時處理數據的情況。
default.html 文件被設置爲每個模板的起始頁面。default.html對應的 JavaScript 文件包含以下對 WinJS.Application.start的調用,該調用會啓動應用事件的分發。
JavaScript
var app = WinJS.Application;
// . . .
app.start();
添加與應用生命週期管理相關的代碼的最佳位置是在 default.js 中。default.js 的實現對所有項目模板而言都相同。此文件包含處理 WinJS onactivated 事件的代碼。當發生 Windows 運行時激活時,將引發該事件。onactivated 事件處理程序中的代碼會檢查應用是否是從 Windows“開始”屏幕啓動,並調用 WinJS.UI.processAll。processAll 函數加載在控件的 DIV 元素中包含 data-win-control屬性的所有控件。此處是包含 processAll 函數的代碼。
JavaScript
app.addEventListener("activated", function (args) {
if (args.detail.kind === activation.ActivationKind.launch) {
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// . . .
} else {
// . . .
}
// . . .
}
args.setPromise(WinJS.UI.processAll().then(function () {
// The code in this section navigates to the current page, if one
// is set, or the home page if a current page is not set.
// . . .
}));
}
});
如果你的代碼需在應用設置其初始狀態時運行,則應將該代碼包含在 WinJS onactivated 事件的處理程序中。如果應用在掛起之後已被重新激活,那麼你可能需要包含其他代碼。在代碼註釋指示的位置添加此代碼。
JavaScript
if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
// TODO: This application has been newly launched. Initialize
// your application here.
} else {
// TODO: This application has been reactivated from suspension.
// Restore application state here.
}
如前所述,模板不包含處理應用掛起的代碼。要在你的代碼中處理這種應用狀態,可以在 WinJS oncheckpoint 事件處理程序中添加代碼,如此處的 default.js 所示,也可添加代碼來註冊 Windows 運行時 suspending 事件的(它將調用oncheckpoint)。
JavaScript
app.oncheckpoint = function (args) {
// TODO: This application is about to be suspended. Save any state
// that needs to persist across suspensions here. If you need to
// complete an asynchronous operation before your application is
// suspended, call args.setPromise().
app.sessionState.history = nav.history;
};
你可以使用 WinJS 或 Windows 運行時事件,或者兩者的組合來管理應用生命期。然而,WinJS 事件和函數對大多數應用而言已足夠了。有關詳細信息,請參閱如何掛起應用和如何恢復應用。
以下是與應用生命週期相關的一些 WinJS 事件和函數:
CSS 樣式
模板的總體行爲和外觀由 CSS 樣式表創建:ui-dark.css。下面是一個定義主要顏色主題、字體和其他樣式屬性的WinJS 樣式表。項目引用在此處顯示:
HTML
<linkhref="//Microsoft.WinJS.1.0/css/ui-dark.css"rel="stylesheet">
你可以在所有 HTML 頁面中將此引用更改爲引用ui-light.css,這是適用於 Windows 應用商店應用的建議備選顏色和樣式主題:
HTML
<linkhref="//Microsoft.WinJS.1.0/css/ui-light.css"rel="stylesheet">
網格和拆分項目模板中的大多數 HTML 頁面都使用一個或多個WinJS 模板(與 Visual Studio 項目和項模板不同)來設定格式並顯示多個數據實例。例如,如果頁面上顯示一個ListView 控件,你將會找到一個類名爲itemtemplate
的 WinJS 模板。類名用於在 JavaScript 文件中檢索元素和指定 CSS。下面是拆分項目模板的 items.html 中的項模板:
HTML
<divclass="itemtemplate"data-win-control="WinJS.Binding.Template">
<divclass="item">
<imgclass="item-image"src="#"data-win-bind="src: backgroundImage; alt: title"/>
<divclass="item-overlay">
<h4class="item-title"
data-win-bind="textContent: title"></h4>
<h6class="item-subtitle win-type-ellipsis"
data-win-bind="textContent: subtitle"></h6>
</div>
</div>
要點 itemtemplate
模板適用於任何類型的
ListView 項,根據上下文不同,該項可能是一個組或單個數據項。
與 HTML 頁面及其 WinJS 模板相關聯的 CSS 樣式是限定範圍的 CSS 樣式。使用限定範圍的樣式可以限制對特定頁面所應用的樣式。這將有助於減少修復由於特定 CSS 樣式源不清晰所導致的問題而花費的時間。以下是使用限定範圍的樣式的示例。items.css中的此部分代碼顯示爲前一個項模板的 IMG 元素設置的 CSS屬性。此元素表示 ListView 中的每個項所關聯的圖像。
CSS
.itemspage .itemslist .item .item-image {
-ms-grid-row-span: 2;
}
在上個示例中,itemspage
條目設置了樣式的作用域,將 CSS 的應用範圍限制爲在 items.html 中聲明的
itemspage
DIV 元素中的元素。itemslist
條目進一步將 CSS 限制爲主頁中的主要內容部分,等等。items.html 中的主要內容部分(聲明ListView)如下所示:
HTML
<divclass="itemslist win-selectionstylefilled"
aria-label="List of groups"
data-win-control="WinJS.UI.ListView"
data-win-options="{ selectionMode: 'none' }">
</div>
處理視圖狀態
“網格”模板和“拆分”模板等項目模板旨在處理一些視圖狀態,包括縱向、貼靠、全屏幕和填充。有關 Windows應用商店應用中的視圖狀態的詳細信息,請參閱佈局指南。網格和拆分模板處理項目模板導航模型中的視圖狀態。有關詳細信息,請參閱導航模型。
導航控件
(PageControlNavigator
)在加載頁面時傳遞位置(頁面 URI)和狀態,它還會使用相同方式傳遞有關視圖狀態的信息。首先,在 navigator.js 中,導航控件爲
window.onresize 事件創建一個處理程序。
JavaScript
window.onresize = this._resized.bind(this);
在 PageControlNavigator
的構造函數代碼中,onresize 事件最終會映射到在與當前 HTML 頁面相關聯的 JavaScript 文件中實現的
updateLayout
函數。在運行時,onresize 事件調用此函數,此函數會將視圖狀態轉發給頁面。
updateLayout
的實現特定於每個頁面。此代碼顯示了“拆分”模板的 items.js 中的updateLayout
和
_initializeLayout
實現。(項頁面是支持用戶從ListView 中選擇組的主頁。用戶選擇組時,應用導航到拆分視圖頁面,即主信息/詳細信息視圖。)
JavaScript
updateLayout: function (element, viewState, lastViewState) {
/// <param name="element" domElement="true" />
var listView = element.querySelector(".itemslist").winControl;
if (lastViewState !== viewState) {
if (lastViewState === appViewState.snapped || viewState === appViewState.snapped) {
var handler = function (e) {
listView.removeEventListener("contentanimating", handler, false);
e.preventDefault();
}
listView.addEventListener("contentanimating", handler, false);
var firstVisible = listView.indexOfFirstVisible;
this._initializeLayout(listView, viewState);
if (firstVisible >= 0 && listView.itemDataSource.list.length > 0) {
listView.indexOfFirstVisible = firstVisible;
}
}
}
},
_initializeLayout: function (listView, viewState) {
if (viewState === appViewState.snapped) {
listView.layout = new ui.ListLayout();
} else {
listView.layout = new ui.GridLayout();
}
},
updateLayout
中的第一行代碼使用querySelector 方法獲取
ListView 控件:
JavaScript
var listView = element.querySelector(".itemslist").winControl;
updateLayout
中的其餘代碼會檢查視圖狀態,設置動畫(未顯示),然後調用_initializeLayout
。_initializeLayout
會設置
ListView 中項的水平或垂直排列。如果當前視圖爲輔屏視圖,則項將垂直排列。否則,項將在網格視圖中排列。
JavaScript
if (viewState === appViewState.snapped) {
listView.layout = new ui.ListLayout();
} else {
listView.layout = new ui.GridLayout();
}
這些代碼示例中顯示的模式由“拆分”模板和“網格”模板使用。“拆分”模板還支持與視圖狀態相關的特有行爲。默認情況下,“拆分”模板中的拆分視圖頁面 (split.html) 是一個兩列視圖 — 主信息/詳細信息視圖。“拆分”模板還定義了一個稱爲單列視圖的備用視圖,適用於視圖狀態爲貼靠或縱向時的情況。定義和處理此視圖狀態的代碼包含在split.js 中。_isSingleColumn
函數定義單列視圖狀態:
JavaScript
_isSingleColumn: function () {
var viewState = Windows.UI.ViewManagement.ApplicationView.value;
return (viewState === appViewState.snapped || viewState === appViewState.fullScreenPortrait);
},
_updateVisibility
函數是 split.js 中調用
_isSingleColumn
的衆多函數之一。_updateVisibility
函數根據當前視圖狀態和選定項啓用和禁用列的可見性。加載頁面時,此函數在 split.js中由
ready 函數調用,在視圖狀態發生更改時還由updateLayout
調用。首先,該函數會刪除主列(如果之前定義了主列,即,如果應用已處於單列視圖)。
JavaScript
_updateVisibility: function () {
var oldPrimary = document.querySelector(".primarycolumn");
if (oldPrimary) {
utils.removeClass(oldPrimary, "primarycolumn");
}
if (this._isSingleColumn()) {
if (this._itemSelectionIndex >= 0) {
utils.addClass(document.querySelector(".articlesection"), "primarycolumn");
document.querySelector(".articlesection").focus();
} else {
utils.addClass(document.querySelector(".itemlistsection"), "primarycolumn");
document.querySelector(".itemlist").focus();
}
} else {
document.querySelector(".itemlist").focus();
}
}
如果應用處於單列視圖,_updateVisibility
會指定一個新的主列,添加與選定項對應的列類型。如果選定了某個項,updateVisibility
會添加項詳細信息部分(HTML 中的
articlesection
),如下所示。
JavaScript
utils.addClass(document.querySelector(".articlesection"), "primarycolumn");
如果未選定任何項,updateVisibility
則會添加項列表部分(HTML 中的
itemlistsection
),如此處所示。
JavaScript
utils.addClass(document.querySelector(".itemlistsection"), "primarycolumn");
split.js 中的多個函數可基於視圖狀態修改“後退”按鈕歷史記錄或導航行爲。ready 函數和
updateLayout
函數可修改“後退”按鈕歷史記錄。selectionChanged
函數(當選定列表視圖中某個項時被調用)可修改導航行爲。