介紹Appcelerator於今年初發表的一套MVC框架-Alloy。它能讓Titanium App開發更有效率,程式碼更易於維護。本文介紹Model和Controller的部分,View請看上篇。
Controller
在Alloy當中Controller包含程式邏輯以控制UI和與Model之間的資料交換。通常View與會與同名的Controller配成一對。
UI元件的參照
如以下的範例:
app/controllers/index.js
function sayHello(e) {
alert("Hello, "+ $.nameTextField.value + "!");
}
$.index.open();
app/views/index.xml
<Alloy>
<Window class="container">
<Label id="nameLabel" class="alignLeft">What is your name?</Label>
<TextField id="nameTextField" class="alignLeft"/>
<Button id="helloButton" onClick="sayHello" class="alignLeft">Say Hello!</Button>
</Window>
</Alloy>
在View內的UI元件,如果有指定id,則可以透過$.id來存取。如:$.nameTextField.value就是id為nameTextField的TextField的值。另一個慣例是$.[controller的名稱],代表的是配對的View當中,最外面的元件。如:$.index就代表了Window。
如果要存取其他的View和Controller,則可使用Alloy.createController()和Controller.getView()來引用。
使用外部Library
如果想用一些外部的Javascript Library,或是不想讓程式邏輯和View有太深的耦合,則可以在app路徑下建立一個名稱為lib的目錄,把這些檔案放進去。在compile成Titanium專案的時候,這些檔案就會自動被複製到Resources目錄內。比如以下例子就是利用Moment.js這個第三方Library,把時間轉換成特定的格式。
var moment = require("moment");
moment.format("MMM Do YY");
Model
Alloy的Model繼承了Backbone的Model與Collection功能,也借用了Rails的遷移和adapter的概念處理各種儲存模式,這代表開發者可以把重點放在資料的結構和處理上,而不是和SQL或其他資料存取相關指令奮戰。目前Alloy Model可存取的資料來源包含sqlite, TitaniumSDK內建的properties和用在HTML5的localStorage等三種方式。如果要用的資料來源不是上面三種,也可以自己撰寫Sync adapter,實作Model和資料來源中間的存取方法。
Model
Alloy的Model繼承Backbone裡的Model class,以Javascript檔案的形式存在。裡面包含資料的結構和處理資料的相關邏輯(如:資料驗證等功能)。Model大致是以下這個樣子:
exports.definition = {
config : {
// 資料結構
"columns": {
"todoItem": "String",
"done": "Bool"
},
// 預設值
"defaults": {
"todoItem": "-",
"done": false
},
// adapter相關設定
"adapter": {
"type": "sql",
"collection_name": "todoList"
}
},
extendModel: function(Model) {
_.extend(Model.prototype, {
// 擴充、覆蓋或實作Backbone.Model
});
return Model;
},
extendCollection: function(Collection) {
_.extend(Collection.prototype, {
// 擴充、覆蓋或實作Backbone.Collection
});
return Collection;
}
}
在Controller裡面可以使用Alloy.createModel來存取Model。比如:
var todo = Alloy.createModel("todo", {todoItem: "Study Alloy framewrok", done: false});
todo.save();
Collection
Alloy裡的Collection是Model的有序集合,繼承自Backbone.Collection class,通常用於準備資料讓UI元件顯示。在Alloy環境當中,如果要在Controller裡存取Collection,可使用Alloy.createCollection()將資料從資料來源讀出。
var todoList = Alloy.createCollection('todo');
todoList.fetch();
Model-View Binding
在Alloy內Collection資料可以同步到TableView、View、ScrollableView、CoverFlowView等UI元件,當資料改變事件發生時這些UI元件顯示的內容也會更新。
要讓Model和View可以自動同步,必須在View當中插入Collection標籤,在要同步的UI元件標籤內加上與資料同步相關的屬性。也要在重複的物件當中,比如TableViewRow中,把要顯示的資料欄為指定到對應的屬性上。
app/views/index.xml
<Alloy>
<Collection src="todo" />
<Window class="container">
<TableView dataCollection="todo">
<TableViewRow title="{todoItem}" hasCheck="(done)" />
</TableView>
</Window>
</Alloy>
$.win.addEventListener("close", function(){
$.destroy();
}
還有一點要特別注意的是,在Model-View Binding已經不需使用的時候,必須要呼叫$.destroy()釋放資源。
$.index.addEventListener('close', function() {
$.destroy();
});
結語
從上面的介紹當中,相信大家也可以發現Alloy確實將很多本來要全部在Javascript裡面時間的功能,有系統的拆解到XML或JSON這樣的檔案格式。這代表分工上會更加方便。程式碼的長度縮短之後,在維護上也會更容易,或許在新的專案上大家可以試試看。由於文章性質的關係,本文僅介紹了Alloy的基本概念,其他功能如:讓UI元件得以重複使用的Widget,方便切換的顯示樣式的Theme,都值得花時間研究。如需詳細的操作方法與API說明,請參考Alloy官方文件。