這篇博文難產了很久,原來是打算一周更新一篇的,上周原計划寫MVC,但是寫了一半,發現帶入了太多的細節,不太符合這個入門系列的主題。 當我們學習一個新的技能的時候,如果一開始就面對大量的細節,很容易陷入其中而只見樹木不見森林,所以最后我想我們還是先按照開發文檔的節奏,一起來做UI5的最佳實踐練習。在練習中對常用的一些控件以及API有一個直觀的感受,如果需要細節的信息再去查文檔。
這個最佳實踐練習的子系列又會分為若干篇,但是不會完全按照Tutorial里面的章節來分,因為我希望每一篇都是都是一個完整的練習,都能跑出來,而不僅僅是一個片段。
最后做出來的App是這樣的。

Figure 1: SAP UI5最佳實踐練習的最終界面
開工吧!
1 首頁
我們先把首頁做出來,還是以之前Hello World的代碼框架開始吧。 首先在 <tomcat>/webapps/下新建一個目錄就叫 ui5bp 吧,創建 index.html ,代碼如下:
index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!--<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> -->
<meta charset="UTF-8">
<title>SAPUI5 Best Practice</title>
<script
id="sap-ui-bootstrap"
src="http://localhost:8080/openui5/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-resourceroots='{
"ui5.tutorial.bp": "./"
}' >
</script>
<script>
</script>
</head>
<body class="sapUiBody">
<!-- This is where you place the UI5 button -->
<div id="content"></div>
</body>
打開瀏覽器,輸入 http://localhost:8080/ui5bp/ 你應該可以看到淡藍色的背景,除此以外,啥都沒有。
這里要提一下,我們定義了一個命名空間 ui5.tutorial.bp 把這個命名空間注冊到根目錄。后續我們定義或者引用資源都需要加上這個命名空間前綴。
打開開發者選項,也沒有任何錯誤,那就成功了,繼續下一步。
2 MVC框架
我們暫時不用Component來做模塊化,我們先用最快最簡單的方法讓程序可以跑出個樣子來,然后再慢慢的添加功能。
所以,我們先直接加入MVC。
簡單介紹下,MVC就是模型、視圖和控制器的簡稱,一般的Web開發都會用到這種架構用來把前端的UI和業務邏輯分離。具體先不多介紹,直接做吧。
我們先大致規划一下,我們的應用是一個主從頁面結構,會有一個Master的頁面和Detail的頁面,我們今天先創建一個Empty頁面來替代Detail。 我們會創建如下文件以及對應的目錄:
ui5bp/ +-- view/ | | | +-- App.view.js | +-- App.controller.js | +-- Empty.view.xml | +-- Master.controller.js | +-- Master.view.xml | +-- model/ | | | +-- mock.json +-- index.html
我們最后把App放入到index的content中,把Master和Detail放到App中去,其中包含 .view. 的文件是視圖,用來定義UI,包含 .controller. 的文件是控制器,用來處理邏輯。 為了簡化應用,我們暫時不使用在線的數據而是用一個json格式的文件數據作為我們的數據模型。這個文件你可以從這里下載。
簡單提一下,視圖可以用html、xml、js、json這四種文件形式來定義,控制器一般則只能用js。
好了,那我們來看每一個文件的代碼。
view/App.view.js
sap.ui.jsview("ui5.tutorial.bp.view.App", {
getControllerName: function () {
return "ui5.tutorial.bp.view.App";
},
createContent: function (oController) {
// to avoid scroll bars on desktop the root view must be set to block display
this.setDisplayBlock(true);
// create app
this.app = new sap.m.SplitApp();
// load the master page
var master = sap.ui.xmlview("Master", "ui5.tutorial.bp.view.Master");
master.getController().nav = this.getController();
this.app.addPage(master, true);
// load the empty page
var empty = sap.ui.xmlview("Empty", "ui5.tutorial.bp.view.Empty");
this.app.addPage(empty, false);
return this.app;
}
});
view/App.controller.js
sap.ui.controller("ui5.tutorial.bp.view.App", {
/**
* Navigates to another page
* @param {string} pageId The id of the next page
* @param {sap.ui.model.Context} context The data context to be applied to the next page (optional)
*/
});
view/Master.view.xml
<core:View
controllerName="ui5.tutorial.bp.view.Master"
xmlns="sap.m"
xmlns:core="sap.ui.core" >
<Page
title="Product List" >
<subHeader>
<Bar>
<contentLeft>
<SearchField
search="handleSearch"
width="100%" >
</SearchField>
</contentLeft>
</Bar>
</subHeader>
<List
id="list"
items="{/SalesOrderCollection}" >
<ObjectListItem
type="Active"
press="handleListItemPress"
title="{SoId}"
number="{GrossAmount}"
numberUnit="{CurrencyCode}" >
<attributes>
<ObjectAttribute text="{BuyerName}" />
</attributes>
</ObjectListItem>
</List>
</Page>
</core:View>
view/Master.controller.js
sap.ui.controller("ui5.tutorial.bp.view.Master", {
handleSearch : function (evt) {
// create model filter
var filters = [];
var query = evt.getParameter("query");
if (query && query.length > 0) {
var filter = new sap.ui.model.Filter("SoId", sap.ui.model.FilterOperator.Contains, query);
filters.push(filter);
}
// update list binding
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(filters);
}
});
view/Empty.view.xml
<core:View
xmlns="sap.m"
xmlns:core="sap.ui.core" >
<Page>
</Page>
</core:View>
最后我們需要把這些文件和首頁關聯起來。 index.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!--<meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/> -->
<meta charset="UTF-8">
<title>SAPUI5 Best Practice</title>
<script
id="sap-ui-bootstrap"
src="http://localhost:8080/openui5/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-resourceroots='{
"ui5.tutorial.bp": "./"
}' >
</script>
<script>
var oView = sap.ui.view({
id : "app",
viewName : "ui5.tutorial.bp.view.App",
type : "JS",
});
// Using a local model for offline development
var oModel = new sap.ui.model.json.JSONModel("model/mock.json");
oView.setModel(oModel);
oView.placeAt('content');
</script>
</head>
<body class="sapUiBody">
<!-- This is where you place the UI5 button -->
<div id="content"></div>
</body>
完工,打開 http://localhost:8080/ui5bp/ ,可以看到下圖:

Figure 2: UI5最佳實踐(一)
3 總結
- Master.view.xml:
這個頁面大概是我們這次教程中最復雜的一個了,其中用到了這些控件:- Page
- Bar
- List
- ObjectListItem
- Master.controler.js:
目前我們只定義了一個方法 - 搜索。 - Empty.view.xml:
只是一個placeholder,因為Detail頁面我們還沒有創建,所以是一個空頁面。 - App.view.js:
容納Master和Detail頁面的容器。 - App.controller.js
之后會在這里定義Master和Detail頁面之間的導航功能
