隨著JavaScript程式變得越來越複雜,往往需要一個團隊協作開發,這時程式碼的模組化和組織規格就變得異常重要了。 MVC模式就是程式碼組織的經典模式。
(…MVC介紹。)
(1)Model
Model表示資料層,也就是程式所需的資料來源,通常使用JSON格式表示。
(2)View
View表示表現層,也就是使用者介面,對網頁來說,就是使用者看到的網頁HTML程式碼。
(3)Controller
Controller表示控制層,用來對原始資料(Model)進行加工,傳送到View。
由於網頁編程不同於客戶端編程,在MVC的基礎上,JavaScript社群產生了各種變體框架MVP(Model-View-Presenter)、MVVM(Model-View-ViewModel)等等,有人就把所有這一類框架的各種模式統稱為MV*。
框架的優點在於合理組織程式碼、便於團隊合作和未來的維護,缺點在於有一定的學習成本,且限制你只能採取它的寫法。
Backbone的載入
Backbone.View
基本用法
Backbone.View方法用來定義視圖類別。
var AppView = Backbone.View.extend({
render: function(){
$('main').append('
一級標題
');
}
});
上面程式碼透過Backbone.View的extend方法,定義了一個視圖類別AppView。該類別內部有一個render方法,用於將視圖放置在網頁上。
使用的時候,需要先新建視圖類別的實例,然後透過實例,呼叫render方法,讓視圖在網頁上顯示。
var appView = new AppView();
appView.render();
上面程式碼新視圖類別AppView的實例appView,然後呼叫appView.render,網頁上就會顯示指定的內容。
新視圖實例時,通常需要指定Model。
var document = new Document({
model: doc
});
initialize方法
視圖也可以定義initialize方法,產生實例的時候,會自動呼叫該方法對實例初始化。
var AppView = Backbone.View.extend({
initialize: function(){
this.render();
},
render: function(){
$('main').append('
一級標題
');
}
});
var appView = new AppView();
上面程式碼定義了initialize方法之後,就省去了產生實例後,手動呼叫appView.render()的步驟。
el屬性,$el屬性
除了直接在render方法中,指定「視圖」所綁定的網頁元素,也可以用視圖的el屬性指定網頁元素。
var AppView = Backbone.View.extend({
el: $('main'),
render: function(){
this.$el.append('
一級標題
');
}
});
上面的程式碼與render方法直接綁定網頁元素,效果完全一樣。上面程式碼中,除了el屬性,還是$el屬性,前者代表指定的DOM元素,後者則表示該DOM元素對應的jQuery物件。
tagName屬性,className屬性
如果不指定el屬性,也可以透過tagName屬性和className屬性指定。
var Document = Backbone.View.extend({
tagName: "li",
className: "document",
render: function() {
// ...
}
});
template方法
視圖的template屬性用來指定網頁範本。
var AppView = Backbone.View.extend({
template: _.template("
Hello "),
});
上面程式碼中,underscore函數庫的template函數,接受一個模板字串作為參數,傳回對應的模板函數。有了這個模板函數,只要提供具體的數值,就能產生網頁程式碼。
var AppView = Backbone.View.extend({
el: $('#container'),
template: _.template("
Hello "),
initialize: function(){
this.render();
},
render: function(){
this.$el.html(this.template({who: 'world!'}));
}
});
上面程式碼的render就呼叫了template方法,進而產生具體的網頁程式碼。
實際應用程式中,一般將範本放在script標籤中,為了防止瀏覽器依照JavaScript程式碼解析,type屬性設為text/template。
可以使用下面的程式碼編譯模板。
window.templates = {};
var $sources = $('script[type="text/template"]');
$sources.each(function(index, el) {
var $el = $(el);
templates[$el.data('name')] = _.template($el.html());
});
events屬性
events屬性用於指定視圖的事件及其對應的處理函數。
var Document = Backbone.View.extend({
events: {
"click .icon": "open",
"click .button.edit": "openEditDialog",
"click .button.delete": "destroy"
}
});
上面程式碼中一個指定了三個CSS選擇器的點選事件,及其對應的三個處理函數。
listento方法
listento方法用於為特定事件指定回呼函數。
var Document = Backbone.View.extend({
initialize: function() {
this.listenTo(this.model, "change", this.render);
}
});
上面程式碼為model的change事件,指定了回呼函數為render。
remove方法
remove方法用於移除一個視圖。
updateView: function() {
view.remove();
view.render();
};
子視圖(subview)
在父視圖中可以呼叫子視圖。下面就是一種寫法。
render : function (){
this.$el.html(this.template());
this.child = new Child();
this.child.appendTo($.('.container-placeholder').render();
}
Backbone.Router
Router是Backbone提供的路由對象,用來將使用者請求的網址與後端的處理函數一一對應。
首先,新定義一個Router類別。
Router = Backbone.Router.extend({
routes: {
}
});
routes屬性
Backbone.Router物件中,最重要的就是routes屬性。它用來設定路徑的處理方法。
routes屬性是一個對象,它的每個成員就代表一個路徑處理規則,鍵名為路徑規則,鍵值為處理方法。
如果鍵名為空字串,就代表根路徑。
routes: {
'': 'phonesIndex',
},
phonesIndex: function () {
new PhonesIndexView({ el: 'section#main' });
}
星號代表任意路徑,可以設定路徑參數,捕捉特定的路徑值。
var AppRouter = Backbone.Router.extend({
routes: {
"*actions": "defaultRoute"
}
});
var app_router = new AppRouter;
app_router.on('route:defaultRoute', function(actions) {
console.log(actions);
})
上面程式碼中,根路徑後面的參數,都會被捕獲,傳入回呼函數。
路徑規則的寫法。
var myrouter = Backbone.Router.extend({
routes: {
"help": "help",
"search/:query": "search"
},
help: function() {
...
},
search: function(query) {
...
}
});
routes: {
"help/:page": "help",
"download/*path": "download",
"folder/:name": "openFolder",
"folder/:name-:mode": "openFolder"
}
router.on("route:help", function(page) {
...
});
Backbone.history
設定了router以後,就可以啟動應用程式。 Backbone.history物件用來監控url的變化。
App = new Router();
$(document).ready(function () {
Backbone.history.start({ pushState: true });
});
打開pushState方法。如果應用程式不在根目錄,就需要指定根目錄。
Backbone.history.start({pushState: true, root: "/public/search/"})
Backbone.Model
Model代表單一的物件實體。
var User = Backbone.Model.extend({
defaults: {
name: '',
email: ''
}
});
var user = new User();
上面程式碼使用extend方法,產生了一個User類,它代表model的模板。然後,使用new指令,產生一個Model的實例。 defaults屬性用來設定預設屬性,上面程式碼表示user物件預設有name和email兩個屬性,它們的值都等於空字串。
產生實例時,可以提供各個屬性的具體值。
var user = new User ({
id: 1,
name: 'name',
email: 'name@email.com'
});
上面程式碼在產生實例時,提供了各個屬性的具體值。
idAttribute屬性
Model實例必須有一個屬性,作為區分其他實例的主鍵。這個屬性的名稱,由idAttribute屬性設定,一般是設為id。
var Music = Backbone.Model.extend({
idAttribute: 'id'
});
get方法
get方法用來傳回Model實例的某個屬性的值。
var user = new User({ name: "name", age: 24});
var age = user.get("age"); // 24
var name = user.get("name"); // "name"
set方法
set方法用來設定Model實例的某個屬性的值。
var User = Backbone.Model.extend({
buy: function(newCarsName){
this.set({car: newCarsName });
}
});
var user = new User({name: 'BMW',model:'i8',type:'car'});
user.buy('Porsche');
var car = user.get("car"); // ‘Porsche'
on方法
on方法用來監聽物件的變化。
var user = new User({name: 'BMW',model:'i8'});
user.on("change:name", function(model){
var name = model.get("name"); // "Porsche"
console.log("Changed my car's name to " name);
});
user.set({name: 'Porsche'});
// Changed my car's name to Porsche
上面程式碼中的on方法用於監聽事件,「change:name」表示name屬性改變。
urlroot屬性
此屬性用於指定伺服器端對model進行操作的路徑。
var User = Backbone.Model.extend({
urlRoot: '/user'
});
上面程式碼指定,伺服器對應該Model的路徑為/user。
fetch事件
fetch事件用於從伺服器取出Model。
var user = new User ({id: 1});
user.fetch({
success: function (user){
console.log(user.toJSON());
}
})
上面程式碼中,user實例含有id屬性(值為1),fetch方法使用HTTP動詞GET,向網址「/user/1」發出請求,從伺服器取出該實例。
save方法
save方法用來通知伺服器新建或更新Model。
如果一個Model實例不含有id屬性,則save方法將使用POST方法新建該實例。
var User = Backbone.Model.extend({
urlRoot: '/user'
});
var user = new User ();
var userDetails = {
name: 'name',
email: 'name@email.com'
};
user.save(userDetails, {
success: function (user) {
console.log(user.toJSON());
}
})
上面程式碼先在類別中指定Model對應的網址是/user,然後新建一個實例,最後呼叫save方法。它有兩個參數,第一個是實例物件的特定屬性,第二個參數是一個回呼函數對象,設定success事件(保存成功)的回呼函數。具體來說,save方法會向/user發出POST請求,並將{name: ‘name', email: ‘name@email.com'}提供為資料。
如果一個Model實例含有id屬性,save方法將使用PUT方法更新該實例。
var user = new User ({
id: 1,
name: '張三',
email: 'name@email.com'
});
user.save({name: '李四'}, {
success: function (model) {
console.log(user.toJSON());
}
});
上面程式碼中,物件實例含有id屬性(值為1),save將使用PUT方法向網址「/user/1」發出請求,從而更新該實例。
destroy方法
destroy方法用於在伺服器上刪除該實例。
var user = new User ({
id: 1,
name: 'name',
email: 'name@email.com'
});
user.destroy({
success: function () {
console.log('Destroyed');
}
});
上面程式碼的destroy方法,將使用HTTP動詞DELETE,向網址「/user/1」發出請求,刪除對應的Model實例。
Backbone.Collection
Collection是同一類Model的集合,例如Model是動物,Collection就是動物園;Model是單一的人,Collection就是一家公司。
var Song = Backbone.Model.extend({});
var Album = Backbone.Collection.extend({
model: Song
});
上面程式碼中,Song是Model,Album是Collection,而且Album有一個model屬性等於Song,因此顯示Album是Song的集合。
add方法,remove方法
Model的實例可以直接放入Collection的實例,也可以用add方法加入。
var Song1 = new Song({ id: 1 ,name: "歌名1", アーティスト: "张三" });
var Song2 = new Music ({id: 2,name: "歌名2", アーティスト: "李思" });
var myAlbum = 新しいアルバム([曲 1, 曲 2]);
var Song3 = new Music({ id: 3, name: " 曲名 3", アーティスト: "Zhao Wu" });
myAlbum.add(song3);
Remove メソッドは、Collection インスタンスから Model インスタンスを削除するために使用されます。
myAlbum.remove(1);
上記のコードは、remove メソッドのパラメーターがモデル インスタンスの id 属性であることを示しています。
get メソッド、set メソッド
get メソッドは、指定された ID を持つ Model インスタンスをコレクションから取得するために使用されます。
myAlbum.get(2))
フェッチメソッド
fetch メソッドは、サーバーからコレクション データを取得するために使用されます。
var songs = 新しいBackbone.Collection;
songs.url = '/songs';
songs.fetch();
バックボーン.イベント
var obj = {};
_.extend(obj, バックボーン.イベント);
obj.on("メッセージの表示", function(msg) {
$('#display').text(msg);
});
obj.trigger("show-message", "Hello World");