目的 template綁定(模板綁定)使用渲染模板的結果填充關聯的DOM元素。 模板是一種簡單方便的方式來構建複雜的UI結構 。 下麵介紹兩種使用模板綁定的方法: 本地模板是支持foreach,if,with和其他控制流綁定的機制。 在內部,這些控制流綁定捕獲元素中包含的HTML標記,並將其用作模板... ...
目的
template綁定(模板綁定)使用渲染模板的結果填充關聯的DOM元素。 模板是一種簡單方便的方式來構建複雜的UI結構 。
下麵介紹兩種使用模板綁定的方法:
參數
快速語法:如果你只是提供一個字元串值,KO會將其解釋為要渲染的模板的ID。它提供給模板的數據將是您當前的模型對象。
要獲得更多控制項,請傳遞具有以下屬性的某些組合的JavaScript對象:
name
— 包含要渲染的模板的元素的ID - 有關如何以編程方式更改此設置,請參見備註5。 nodes
—直接傳遞DOM節點數組以用作模板。這應該是一個不可觀察的數組,並註意元素將從他們當前的父(如果他們有一個)中刪除。如果您還為name傳遞了一個非空值,則忽略此選項。 data
— 要提供為要呈現的模板的數據的對象。如果省略此參數,KO將查找foreach參數,或者使用當前模型對象返回。 if
— 如果提供此參數,那麼只有在指定的表達式求值為true(或true-ish值)時,才會呈現模板。這可以有助於防止null observable在填充之前與模板綁定。 foreach
— 指示KO以“foreach”模式渲染模板 - 有關詳細信息,請參見備註2。 as
— 當與foreach結合使用時,為正在呈現的每個項目定義別名 - 有關詳細信息,請參見備註3。 afterRender
, afterAdd
, beforeRemove
— 要針對呈現的DOM元素調用的回調函數 - 請參閱備註4 備註1:渲染命名模板
通常,當您使用控制流綁定(foreach,with,if等)時,不需要給您的模板命名:它們是由DOM元素內的標記隱式和匿名定義的。 但是如果你想要,你可以將模板分解成一個單獨的元素,然後通過名稱引用它們:
Participants
Here are the participants:源碼:
<h2>Participants</h2> Here are the participants: <div data-bind="template: { name: 'person-template', data: buyer }"></div> <div data-bind="template: { name: 'person-template', data: seller }"></div> <script type="text/html" id="person-template"> <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p> </script> <script type="text/javascript"> function MyViewModel() { this.buyer = { name: 'Franklin', credits: 250 }; this.seller = { name: 'Mario', credits: 5800 }; } ko.applyBindings(new MyViewModel()); </script>
在此示例中,'person-template'標記使用兩次:一次用於買方,一次用於賣方。 請註意,模板標記被包裝在<script type =“text / html”>中 - 必須使用虛擬類型屬性,以確保標記不會作為JavaScript執行,Knockout不會嘗試對該標記應用綁定,除非 它被用作模板。
使用命名模板不是經常被用到,但有時它可以幫助減少重覆的標記。
備註2:對命名模板使用“foreach”選項
Participants
Here are the participants:源碼:
<h2>Participants</h2> Here are the participants: <div data-bind="template: { name: 'person-template', foreach: people }"></div> <script type="text/html" id="person-template"> <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p> </script> <script> function MyViewModel() { this.people = [ { name: 'Franklin', credits: 250 }, { name: 'Mario', credits: 5800 } ] } ko.applyBindings(new MyViewModel()); </script>
這給出了與在您使用foreach的元素內直接嵌入匿名模板相同的結果,例如:
<div data-bind="foreach: people"> <h3 data-bind="text: name"></h3> <p>Credits: <span data-bind="text: credits"></span></p> </div>
備註3:使用“as”給“foreach”項目一個別名
當嵌套foreach模板時,引用層次結構中較高級別的項目通常很有用。 一種方法是在綁定中引用$ parent或其他綁定上下文變數。
然而,一個更簡單和更優雅的選項是使用as來為你的迭代變數聲明一個名字。 例如:
<ul data-bind="template: { name: 'employeeTemplate', foreach: employees, as: 'employee' }"></ul>
註意與as相關聯的字元串值“employee”。 現在在這個foreach迴圈中的任何地方,你的子模板中的綁定將能夠引用employee來訪問正在呈現的employee對象。
如果你有多個嵌套的foreach塊,這是非常有用的,因為它給你一個明確的方法來引用層次結構中更高級別上聲明的任何命名項。 這是一個完整的例子,顯示季節可以在渲染一個月時被引用:
源碼:
<ul data-bind="template: { name: 'seasonTemplate', foreach: seasons, as: 'season' }"></ul> <script type="text/html" id="seasonTemplate"> <li> <strong data-bind="text: name"></strong> <ul data-bind="template: { name: 'monthTemplate', foreach: months, as: 'month' }"></ul> </li> </script> <script type="text/html" id="monthTemplate"> <li> <span data-bind="text: month"></span> is in <span data-bind="text: season.name"></span> </li> </script> <script> var viewModel = { seasons: ko.observableArray([ { name: 'Spring', months: [ 'March', 'April', 'May' ] }, { name: 'Summer', months: [ 'June', 'July', 'August' ] }, { name: 'Autumn', months: [ 'September', 'October', 'November' ] }, { name: 'Winter', months: [ 'December', 'January', 'February' ] } ]) }; ko.applyBindings(viewModel); </script>
提示:請記住將字元串字面值傳遞為as(例如,as:'season',而不是as:season),因為您要出給一個新變數命名,而不是讀取已經存在的變數的值。
備註4:使用afterRender, afterAdd, beforeRemove
有時,您可能希望對由模板生成的DOM元素運行自定義後處理邏輯。 例如,如果您使用JavaScript視窗部件庫(如jQuery UI),則可能需要攔截模板的輸出,以便可以對其運行jQuery UI命令,將一些渲染的元素轉換為日期選擇器,滑塊或別的什麼東西。
通常,對DOM元素執行此類後處理的最佳方法是編寫自定義綁定,但如果您只想訪問模板發出的原始DOM元素,則可以使用afterRender。
傳遞函數引用(函數文字,或給出視圖模型上的函數名稱),Knockout將在渲染或重新渲染模板後立即調用它。 如果你使用foreach,Knockout將為添加到你的observable數組的每個項目調用你的afterRender回調函數。 例如,
<div data-bind='template: { name: "personTemplate", data: myData, afterRender: myPostProcessingLogic }'> </div>
併在視圖模型(即包含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 }
如果您正在使用foreach,並且只希望通知有關特定要添加或正在刪除的元素,則可以使用afterAdd和beforeRemove。 有關詳細信息,請參閱第四章foreach綁定的文檔。
備註5:動態選擇使用哪個模板
如果有多個命名模板,則可以為名稱選項傳遞observable。 隨著observable的值被更新,元素的內容將使用適當的模板重新渲染。 或者,您可以傳遞迴調函數來確定要使用哪個模板。 如果您使用的是foreach模板模式,Knockout將評估數組中每個項目的函數,並將該項目的值作為唯一的參數。 否則,函數將給出數據選項的值,或者返回提供整個當前模型對象。
源碼:
<ul data-bind='template: { name: displayMode, foreach: employees }'> </ul> <script> 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) { // Initially "Kari" uses the "active" template, while the others use "inactive" return employee.active() ? "active" : "inactive"; } }; // ... then later ... viewModel.employees()[1].active(true); // Now "Brynn" is also rendered using the "active" template. </script>
如果你的函數引用了observable值,那麼當這些值發生變化時,綁定就會更新。 這將導致使用適當的模板重新呈現數據。
如果你的函數包含第二個參數,那麼它將接收整個綁定上下文。 然後,當動態選擇模板時,可以訪問$ parent或任何其他綁定上下文變數。 例如,您可以修改上述代碼段,如下所示:
displayMode: function(employee, bindingContext) { // Now return a template name string based on properties of employee or bindingContext }
備註6:使用jQuery.tmpl,一個外部的基於字元串的模板引擎
在絕大多數情況下,Knockout的本地模板和foreach,if,with和其他控制流綁定將需要構建一個任意複雜的UI。 但是,如果您希望與外部模板庫(例如Underscore模板引擎或jquery.tmpl)集成,Knockout提供了一種方法。
預設情況下,Knockout支持jquery.tmpl。 要使用它,您需要按以下順序引用以下庫:
<!-- First jQuery --> <script src="http://code.jquery.com/jquery-1.7.1.min.js"></script> <!-- Then jQuery.tmpl --> <script src="jquery.tmpl.js"></script> <!-- Then Knockout --> <script src="knockout-x.y.z.js"></script>
然後,您可以在模板中使用jQuery.tmpl語法。 例如
<h1>People</h1> <div data-bind="template: 'peopleList'"></div> <script type="text/html" id="peopleList"> {{each people}} <p> <b>${name}</b> is ${age} years old </p> {{/each}} </script> <script type="text/javascript"> var viewModel = { people: ko.observableArray([ { name: 'Rod', age: 123 }, { name: 'Jane', age: 125 }, ]) } ko.applyBindings(viewModel); </script>
這是因為{{each ...}}和$ {...}是jQuery.tmpl語法。 更重要的是,嵌套模板很簡單:因為您可以在模板中使用數據綁定屬性,您可以簡單地在模板中放置一個data-bind =“template:...”來渲染嵌套的模板。
請註意,截至2011年12月,jQuery.tmpl已不再處於積極開發階段。 我們建議使用Knockout的本地基於DOM的模板(即foreach,if,with等綁定),而不是jQuery.tmpl或任何其他基於字元串的模板引擎。