Knockout應用開發指南 第四章:模板綁定

模板綁定The template binding

目的javascript

template綁定經過模板將數據render到頁面。模板綁定對於構建嵌套結構的頁面很是方便。默認狀況, Knockout用的是流行的jquery.tmpl模板引擎。使用它的話,須要在安裝頁面下載和引用jquery.tmpl和jQuery框架。或者你也能夠集成其它的模板引擎(雖然須要瞭解Knockout 內部知識才行)。css

 

例子html

<div data-bind='template: "personTemplate"'> </div>
<script id='personTemplate' type='text/html'>
${ name } is ${ age } years old
<button data-bind='click: makeOlder'>Make older</button>
</script>

<script type='text/javascript'>
var viewModel = {
name: ko.observable('Bert'),
age: ko.observable(78),
makeOlder: function () {
this.age(this.age() +1);
}
};
ko.applyBindings(viewModel);
</script>

當引用的observable(dependent observable)數據改變的時候,Knockout會自動從新render模板。在這個例子裏,每次點擊button的時候都會從新render模板。java

 

語法node

你可使用任何你模板引擎支持的語法。jquery.tmpl執行以下語法:jquery

 

和observable數組一塊兒使用{{each}}編程

固然使用{{each someArray}}的時候,若是你的值是observableArray,你必須使用JavaScript類型的基礎數組類型{{each myObservableArray()}},而不是{{each myObservableArray}}。api

 

參數數組

    主參數緩存

        語法快速記憶:若是你聲明的僅僅是字符串(上個例子),KO會使用模板的ID來render。應用在模板上的數據是你的整個view model對象(例如ko.applyBindings 綁定的對象)。

        更多控件,你能夠傳帶有以下屬性的JavaScript對象:

            name(必選項) — 須要render的模板ID – 參考 注5 如何使用function函數聲明ID。

            data(可選項) — 須要render到模板的數據。若是你忽略整個參數,KO將查找foreach參數,或者是應用整個view model對象。

            foreach(可選項) — 指定KO按照「foreach」模式render模板 – 參考 注3。

            afterAdd或beforeRemove(可選項) — 在foreach模式下使用callback函數。

            templateOptions(可選項) — 在render模板的時候,傳遞額外數據以便使用。參考 注6。

 

傳遞多個參數的例子:

<div data-bind='template: { name: "personTemplate", data: someObject }'> </div>

 

注1:Render嵌套模板

由於在模板裏使用的是data-bind屬性來聲明的,因此嵌套模板你能夠再次使用data-bind='template: ...',在上層模板的元素裏。

這比模板引發的原生語法好用多了(例如jquery.tmpl裏的{{tmpl}})。Knockout語法的好處在於能夠在每層模板的跟着相關的依賴值,因此若是依賴改變了,KO將只會從新render依賴所在的那個模板。這將很大地改善了性能。

 

注2:${ val }和<span data-bind='text: val'></span>有何不一樣?

當你在模板內部使用data-bind屬性的時候,KO是單獨爲這個綁定單獨跟蹤依賴項的。當model改變的時候,KO只會更新綁定的元素以及子元素而不須要從新render整個模板。因此若是你聲明這樣的代碼是<span data-bind='text: someObservableValue'></span>,當 someObservableValue改變的時候,KO將只是簡單地更新<span>元素的text值而不須要從新render整個模板。

不過,若是模板內部使用的observable值(例如${ someObservableValue }),若是這個observable值改變了,那KO將從新render整個模板。

這就是說,不少狀況下<span data-bind='text: someObservableValue'></span>性能要比${ someObservableValue }要好,由於值改變的話不會影響臨近元素的狀態。不過${ someObservableValue }語法比較簡潔,若是你的模板比較小的話,仍是更合適的,不會帶來大的性能問題。

 

注3:使用foreach

若是須要爲集合裏的每個item render一次模板,有2種方式:

    你可使用模板引擎裏的原生「each」語法,對jquery.tmpl來講就是用{{each}}語法迭代數組。

    另一種方式就是用Knockout的foreach模式來render。

 

例子:

<div data-bind='template: { name: "personTemplate",
foreach: someObservableArrayOfPeople }'> </div>

 

foreach模板模式的好處是:

  • 當往你的collection集合裏添加新item項的時候,KO只會對這個新item進行render模板,而且將結果附加到現有的DOM上。
  • 當從collection集合裏刪除item的時候,KO將不會從新render任何模板,而只是簡單地刪除相關的元素。
  • KO容許經過自定義的方式聲明afterAdd和beforeRemove的callback函數添加/刪除DOM元素。而後這個callback會在刪除元素的時候進行一些動畫或者其它操做。

與原生的each不一樣之處是:在改變以後,模板引擎強制從新render模板裏全部的內容,由於它根本就不關注KO裏所謂的依賴跟蹤內容。

關於使用foreach模式的例子,參考grid editor和animated transitions。

 

注4:使用afterRender選項

有時候,你須要在模板生成的DOM元素上深度定義邏輯。例如,你可能想再模板輸出的時候進行截獲,而後在render的元素上容許jQuery UI命令(好比date picker,slider,或其它)。

你可使用afterRender選項,簡單聲明一個function函數(匿名函數或者view model裏的函數),在render或者從新render模板以後Knockout會從新調用它。若是你使用的是foreach,那在每一個item添加到observable數組以後, Knockout會當即調用afterRender的callback函數。例如,

<div data-bind='template: { name: "personTemplate",
data: myData,
afterRender: myPostProcessingLogic }'> </div>

… 在view model裏聲明一個相似的函數(例如,對象包含myData):

viewModel.myPostProcessingLogic = function (elements) {
// "elements" is an array of DOM nodes just rendered by the template
// You can add custom post-processing logic here
}

 

注5:動態決定使用哪一個模板

有時候,你可能須要根據數據的狀態來決定使用哪一個模板的ID。能夠經過function的返回ID應用到name選擇上。若是你用的是foreach模板模式, Knockout會對每一個item執行function(將item做爲參數)從而將返回值做爲ID,不然,該function接受的參數是整個 data option或者是整個view model。

 

例子:

<ul data-bind='template: { name: displayMode,
foreach: employees }'> </ul>
<script type='text/javascript'>
var viewModel = {
employees: ko.observableArray([
{ name: "Kari", active: ko.observable(true) },
{ name: "Brynn", active: ko.observable(false) },
{ name: "Nora", active: ko.observable(false) }
]),
displayMode: function (employee) {
return employee.active() ?"active" : "inactive";
// Initially "Kari" uses the "active" template, while the others use "inactive"
}
};

// ... then later ...
viewModel.employees()[1].active(true);
// Now "Brynn" is also rendered using the "active" template.
</script>

若是你的function引用的是observable值,那當這些值改變的時候,綁定的值會隨着改變的。這將致使相應的模板從新render。

 

注6:使用templateOptions傳遞額外的參數

若是你在綁定模板的時候須要傳入額外的數據的話,你可使用templateOptions對象來傳遞這些值。這能夠幫助你經過一些 不屬於view model過濾條件或者字符來重用模板。另一個好處是用在範圍控制,你能夠引用經過你的模板訪問怒道的數據。

 

例子,

<ul data-bind='template: { name: "personTemplate",
foreach: employees,
templateOptions: { label: "Employee:",
selectedPerson: selectedEmployee } }'> </ul>


<script id='personTemplate' type='text/html'>
<div data-bind="css: { selected: $data === $item.selectedPerson()" }">
${ $item.label } <input data-bind="value: name" />
</div>
</script>

在整個例子裏,personTemplate有可能都使用employee和自定義對象。經過templateOptions咱們能夠傳遞一個字符label和當前已選擇項做爲selectedPerson來控制style。在jquery.tmpl模板裏,這些值能夠經過訪問$item對象的屬性獲得。

 

注7:模板是被預編譯和緩存的

爲了最大性能,Knockout內嵌模板引擎jquery.tmpl會利用自身的功能對你的模板進行預編譯成可執行的JavaScript代碼,而後從編譯流程裏緩存輸出。這將使模板更快更加具備可執行性,尤爲是是使用foreach循環來render相同模板的時候。

通常狀況你不會注意到這個,因此常常會忘記。不過,當你在某種緣由下經過編程重寫模板<script>元素的時候而且該模板以前已經用過一次的話,你的改變不會帶來任何render的變化,由於在第一次使用的時候已經預編譯了而且緩存起來了。(若是這些會帶來問題,咱們將考慮在KO新版本里提供一個禁用或重設模板緩存的功能,不過好像沒有好的緣由去動態改變模板<script>元素的內容)。

 

注8:使用不一樣的模板引擎

若是你想使用不一樣的JavaScript模板引擎(或者是由於某些緣由你不想在jQuery上使用依賴)。咱們能夠去爲KO來寫一個不一樣的模板引擎,例如,在KO源代碼裏的jqueryTmplTemplateEngine.js,儘管他是爲了支持多個版本的jquery.tmpl而編譯。支持一個單獨的模板引擎版本相對簡單多了。

 

依賴性

template綁定只能在引用合適的模板引擎狀況下才能工做。例如提到的jquery.tmpl引擎。

 

點擊查看本系列教程目錄

相關文章
相關標籤/搜索