Template範本(或稱為樣版)功能主要用於同一組輸出樣式需反覆套用多次的情境,在先前foreach範例中,<tbody>內含的HTML元素便是一種範本,重複套用在每一筆資料以產生<tr>。除了將範本直接定義在容器元素內,範本內容也可另存於<script type="text/html" id="tmpl_id"></script>中(將範本定義藏在<script>的技巧,在jQuery Template也看過,可以盡情撰寫HTML標籤,也不用擔心干擾到正常DOM,此做法在JavaScript的範本架構中蠻普遍),宣告data-bind時則寫成:

<tbody data-bind="template: { name: 'tmpl_id', foreach: users }"> (多筆資料)

<div data-bind="template: { name: 'tmpl_id', data: boo }"> (單筆資料)

當同一個範本會重複用於兩處以上data-bind宣告時,此種做法可達到範本共用的效果。例如,在頁面上有兩個<div>,要分別顯示隊長跟一群隊員的連絡資料,由於每筆連絡資料的呈現格式相同,故我們將連線資料範本抽出來定義於<script>中,同時做為兩個<div>的範本來源。

在套用範本產生HTML元素過程中,KO提供了三個事件可供掛載自訂邏輯:

  • afterRender: 產生HTML元素後觸發,會傳入elements參數供程式存取所產生的元素
  • afterAdd: 適用於foreach,發生於陣列加入元素後 (請參見範例6)
  • beforeRemove: 適用於foreach,發生於陣列移除元素前 (請參見範例6)

在本範例中,我在隊長的afterRender事件加入姓名及電話文字的閃爍特效,大家可到 線上展示 體驗。

完整程式碼如下:

<!DOCTYPE html>
 
<html>
<head>
    <title>Lab 13 - Template範本功能</title>
    <script src="../Scripts/jquery-1.7.2.js"></script>
    <script src="../Scripts/knockout-2.1.0.debug.js"></script>
    <script type="text/html" id="contactTmpl">
        <dl class='cont-block'>
        <dt>Name</dt><dd data-bind="text:name"></dd>    
        <dt>Phone</dt><dd data-bind="text:phone"></dd>
        </dl>
    </script>
 
    <script>
        function Contact(name, phone) {
            this.name = name;
            this.phone = phone;
        }
 
        function MyViewModel() {
            var self = this;
            self.leader = ko.observable();
            self.members = ko.observableArray();
            self.afterRenderEvent = function (elements) {
                //依範本產生元素後觸發,加上閃爍動畫
                $(elements).find("dd")
                .animate({ opacity: 0 }, 500)
                .animate({ opacity: 1 }, 500);
            };
        }
 
        $(function () {
            var vm = new MyViewModel();
            vm.leader(new Contact("美國隊長", "0800092000"));
            vm.members.push(new Contact("鋼鐵人", "28825252"));
            vm.members.push(new Contact("索爾", "23939889"));
            vm.members.push(new Contact("浩克", "0800956956"));
            ko.applyBindings(vm);
        });
    </script>
    <style>
        .cont-block 
        {
            font-family: Segoe UI; font-size: 10pt;
            border: 1px solid gray; padding: 5px; width: 135px;
            border-radius: 4px; box-shadow: 5px 5px 10px #444;
        }
        .memb-list .cont-block { float: left; margin-right: 15px; }
        dt { font-weight: bold; color: purple; }
        dd { color: brown; }
    </style>
</head>
<body>
<h3>Leader</h3>
<div data-bind="template: { name: 'contactTmpl', data: leader, afterRender: afterRenderEvent  }"></div>
<br />
<h3>Members</h3>
<div data-bind="template: { name: 'contactTmpl', foreach: members }" class='memb-list'></div>
</body>
</html>

除了使用KO自己的範本語法,KO也支援其他範本程式庫jQuery TemplateUnderscore template engine等,不需在容器元素上宣告foreach,而是直接在範本中使用{{each users}}、${name}語法形成迴圈或叫用屬性 ( Underscore語法則是用<% _.each(user(), function(user) { %>與<%= user.name %>語法 ),大家可視需要採用。

註: jQuery.tmpl已停止發展了,預計將由jsView及jsRender接手,但依現在微軟對knockout.js愈發倚重的態勢,加上KO在開發社群已獲高度觀注,個人推測jsView/jsRender有可能因棄保效應漸漸為人所淡忘...

[KO系列]
http://www.darkthread.net/kolab/labs/default.aspx?m=post

Comments

Be the first to post a comment

Post a comment


47 + 11 =