天天看點

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

目的

template綁定通過模闆将資料render到頁面。模闆綁定對于建構嵌套結構的頁面非常友善。預設情況, Knockout用的是流行的jquery.tmpl模闆引擎。使用它的話,需要在安裝頁面下載下傳和引用jquery.tmpl和jQuery架構。或者你也可以內建其它的模闆引擎(雖然需要了解Knockout 内部知識才行)。

例子

當引用的observable(dependent observable)資料改變的時候,Knockout會自動重新render模闆。在這個例子裡,每次點選button的時候都會重新render模闆。

文法

你可以使用任何你模闆引擎支援的文法。jquery.tmpl執行如下文法:

和observable數組一起使用{{each}}

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

參數

    主參數

        文法快速記憶:如果你聲明的僅僅是字元串(上個例子),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。

傳遞多個參數的例子:

注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。

例子:

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函數。例如,

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

注5:動态決定使用哪個模闆

有時候,你可能需要根據資料的狀态來決定使用哪個模闆的ID。可以通過function的傳回ID應用到name選擇上。如果你用的是foreach模闆模式, Knockout會對每個item執行function(将item作為參數)進而将傳回值作為ID,否則,該function接受的參數是整個 data option或者是整個view model。

如果你的function引用的是observable值,那當這些值改變的時候,綁定的值會随着改變的。這将導緻相應的模闆重新render。

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

如果你在綁定模闆的時候需要傳入額外的資料的話,你可以使用templateOptions對象來傳遞這些值。這可以幫助你通過一些 不屬于view model過濾條件或者字元來重用模闆。另外一個好處是用在範圍控制,你可以引用通過你的模闆通路怒道的資料。

例子,

在整個例子裡,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引擎。

繼續閱讀