2013/04/25

初次玩 Backbone.js: 多種 Template 的實作方式

假設我想設計一個公司資料,model 為單一員工資料,包含 id 與 name。collection 為部門資料,由多個員工所組成。而 view 用來顯示部門資料之用。
// Models
company.models.Employee = Backbone.Model.extend({
    defaults: {
        id: undefined,
        name: undefined
    }
});

// Collections
company.collections.Department = Backbone.Collection.extend({
    model: company.models.Employee
});

// Views
company.views.EmployeeList = Backbone.View.extend({
    el: "#container",
 
    render: function() {
        ...
    }
});

// Create base data
var c = new company.collections.Department(
        [{id:1, name: "Star Willard"},
         {id:2, name: "Rhona Eggleston"},
         {id:3, name: "Cassi Chowdhury"},
         {id:4, name: "Leigh Nilson"},
         {id:5, name: "Niesha Auger"}
        ]);

// Create view
var v = new company.views.EmployeeList({collection: c});
v.render();


以下就來探討 render function 該怎麼把 collection 套用到 template 並呈現在 UI 上


方法一:土法煉鋼,串成 string


這種方法當然是很差啦,程式可讀性下降,也很難維護

Render function in app.js
render: function() {
    var that = this;
    this.collection.each(function(m) {
        var html = "<div>" + 
                   "" + m.get("id") + " " + 
                   "" + m.get("name") + "" + 
                   "</div>";
        that.$(".list").append(html);
    });
    return this;
}


方法二:寫在 stript 內


利用 underscore.js template engine
比前一種好一點點,但還是有缺點,沒有把 template 切出去,一方面 IDE 的 syntax 會失效

in index.html
<script id="template-item" type="text/template">
    <div>
        <b><%= id %></b>
        <u><%= name %></u>
    </div>
</script>
Render function in app.js
template: _.template($("#template-item").html()),
  
render: function() {
    var that = this;
    this.collection.each(function(m) {
     that.$(".list").append(that.template(m.toJSON()));
    });
    return this;
}


方法三:從獨立的 html 檔案中讀取


把 template 寫在個別的 html 檔,利用 ajax 的方式去 load。
程式碼較好管理,但每讀取一次 template 就要多發一個 http request

tpl/template-item.html
<%= id %> <%= name %>

Add the template manager to app.js
其實只是把 get request 包起來啦
company.utils.TemplateManager = {
    load: function(name, callback) {
        $.get('tpl/' + name + '.html', function(data) {
            callback(data);
        });
    }
};

Render function in app.js
render: function() {
    var that = this;
    company.utils.TemplateManager.load('template-item', function(data) {
        var tpl = _.template(data);
        that.collection.each(function(m) {
            that.$(".list").append(tpl(m.toJSON()));
        });
    });
    return this;
}


方法四:Asynchronously load template


與其說是非同步,正確來說應該是預先載入(preload),之後使用時就可以直接從 local variable 取出,加快反應速度,也可以省去從 server 抓取相同 template 的功耗

TemplateLoader in app.js
company.utils.TemplateManager = {
    templates: {},
    
    load: function(names) {
        var that = this;
        $.each(names, function(index, name) {
            $.get('tpl/' + name + '.html', function(data) {
                that.templates[name] = data;
            });
        });
    },
    
    get: function(name, callback) {
        return this.templates[name];
    }
};

Render function in app.js
render3: function() {
    var that = this;
    var tpl = _.template(company.utils.TemplateManager.get('template-item'));
    this.collection.each(function(m) {
        that.$(".list").append(tpl(m.toJSON()));
    });
}

in app.js
Preload the template before render the view.
company.utils.TemplateManager.load(['template-item', 'other-template']);
var v = new company.views.EmployeeList({collection: c});
v.render();

如果要保證全部的 template 都載入才進行之後的事情,可以使用 jquery.when()
load: function(names, callback) {
    var deferreds = [];
    var that = this;
    $.each(names, function(index, name) {
        deferreds.push($.get('tpl/' + name + '.html', function(data) {
            that.templates[name] = data;
        }));
    });
    $.when.apply(null, deferreds).done(callback);
}


參考資料


1 則留言:

  1. Heater Bands – Heat the barrel and keep it at an appropriate, even temperature to arrange the soften. Particularly in case MOTORCYCLE RAIN GEAR your wants are specialised or unique, discovering a provider that understands your business, materials, and challenges is crucial to the success of the project. High Impact Polystyrene is polystyrene to which rubber has been added to extend energy. It is an inexpensive choice for applications that require rigidity and dimensional energy.

    回覆刪除