本文是【Knockout.js 學習體驗之旅】系列文章的第3篇,全部demo均基於目前knockout.js的最新版本(3.4.0)。小茄才識有限,文中如有不當之處,還望你們指出。javascript
目錄: html
【Knockout.js 學習體驗之旅】(1)ko初體驗前端
【Knockout.js 學習體驗之旅】(2)花式捆綁java
【Knockout.js 學習體驗之旅】(3)模板綁定node
頁面是由數據和HTML組件構成的,如何將數據嵌入到HTML組件裏面呢?一個比較好的選擇是使用模板技術。jquery
回顧下第一篇(【Knockoutjs 學習體驗之旅】(1)ko初體驗)開頭的總價計算:數組
1 <!--HTML Code--> 2 <div class="counter"> 3 Price: <input type="text" data-bind="{value: price, valueUpdate: 'afterkeydown'}" placeholder="請輸入單價" /><br /> 4 Account: <input type="text" data-bind="textInput: account" placeholder="請輸入個數" /><br /> 5 sum: <span data-bind="text: sum"></span> 6 </div>
這就是一個簡單的組件,他有本身的內部結構,有本身的事件處理機制。假如我須要使用不少個這樣的組件,那確定不會是將上面的HTML代碼複製 n 遍插入到不一樣的地方吧,何況單純複製還不行,還要將變量區分開呢!若是是在一個列表裏面,那能夠用 foreach 來作,若是是要用在不一樣的容器內,那就要使用模板引擎技術了。服務器
模板技術並非什麼高深的東西,有基於字符串拼接技術的,有基於 DOM 節點的,還有混合着的。更具體的介紹能夠看一看這個輪子哥的文章 http://www.tuicool.com/articles/qMJ77r,樓主就不班門弄斧了。knockout.js 也是基於DOM節點的模板技術,編譯以後 view 與 data 仍是保持綁定關係,能夠簡單方便地更新數據到 view 層。另外你也能夠將 knockout.js 連接到第三方的模板引擎,如 jquery.tmpl 和 Underscore等模板引擎。網絡
下面簡單講講ko中模板綁定的使用,第三方的集成引用不在本文討論範圍內。app
先看一個例子:
1 <h2>Participants</h2> Here are the participants: 2 <div data-bind="template: { name: 'person-template', data: buyer }"></div> 3 <div data-bind="template: { name: 'person-template', data: seller }"></div> 4 5 <!--模板--> 6 <script type="text/html" id="person-template"> 7 <h3 data-bind="text: name"></h3> 8 <p>Credits: <span data-bind="text: credits"></span></p> 9 </script> 10 11 <script type="text/javascript"> 12 function MyViewModel() { 13 this.buyer = { name: 'Franklin', credits: 250 }; 14 this.seller = { name: 'Mario', credits: 5800 }; 15 } 16 ko.applyBindings(new MyViewModel()); 17 </script>
<script type="text/html" id="person-template">這個script腳本標籤訂義了一個 id 爲"person-template"的模板,ko就是經過這個 id 來尋找相應的模板。注意這個腳本的 type 是"text/html",因此才能跟正常的腳本區分開。ko不會自動綁定在這種腳本內的代碼,只有在這個模板被使用的時候纔會去綁定。
使用方法:HTML元素中使用 data-bind 綁定用到的模板,在 js 中定義相應的數據並應用該綁定。能夠看到上面的"person-template"被引用了兩次,一次使用的是buyer的數據,另外一次使用了seller數據。下面簡單說說模板綁定中用到的參數:
下面簡單簡單介紹一下幾種用法。
1 <h2>Participants</h2> 2 Here are the participants: 3 <div data-bind="template: { name: 'person-template', foreach: people }"></div> 4 5 <script type="text/html" id="person-template"> 6 <h3 data-bind="text: name"></h3> 7 <p>Credits: <span data-bind="text: credits"></span></p> 8 </script> 9 10 function MyViewModel() { 11 this.people = [ 12 { name: 'Franklin', credits: 250 }, 13 { name: 'Mario', credits: 5800 } 14 ] 15 } 16 ko.applyBindings(new MyViewModel());
這個例子跟上面的例子效果是同樣的,使用 foreach 會將全部數據都渲染到模板中。區別就在於HTML的層級,使用data指定的時候,每一份數據渲染到對應的容器中;使用foreach的時候全部數據都被綁定到了一個容器內。上一篇中也介紹了foreach的用法,用不用模板都能獲得同樣的效果。回憶一下foreach的寫法:
1 <div data-bind="foreach: people"> 2 <h3 data-bind="text: name"></h3> 3 <p>Credits: <span data-bind="text: credits"></span></p> 4 </div>
1 <ul data-bind="template: { name: 'seasonTemplate', foreach: seasons, as: 'season' }"></ul> 2 3 <script type="text/html" id="seasonTemplate"> 4 <li> 5 <strong data-bind="text: name"></strong> 6 <ul data-bind="template: { name: 'monthTemplate', foreach: months, as: 'month' }"></ul> 7 </li> 8 </script> 9 10 <script type="text/html" id="monthTemplate"> 11 <li> 12 <span data-bind="text: month"></span> 13 is in 14 <span data-bind="text: season.name"></span> 15 </li> 16 </script> 17 18 <script> 19 var viewModel = { 20 seasons: ko.observableArray([ 21 { name: 'Spring', months: [ 'March', 'April', 'May' ] }, 22 { name: 'Summer', months: [ 'June', 'July', 'August' ] }, 23 { name: 'Autumn', months: [ 'September', 'October', 'November' ] }, 24 { name: 'Winter', months: [ 'December', 'January', 'February' ] } 25 ]) 26 }; 27 ko.applyBindings(viewModel); 28 </script>
上面這種多層的綁定中,要在下級綁定層次中要引用上層的話,就可使用 as 定義的別名了。固然層次簡單的時候,用$parent也是能夠的,用 as 會更加清晰,不會糾結在層次關係中。
注意:as 後接的別名應該用引號引發來,由於這裏咱們是命名一個變量,而不是讀取一個已經存在的變量。
1 <ul data-bind='template: { name: displayMode, foreach: employees }'> </ul> 2 <script id="active" type='text/html'> 3 <li><span data-bind='text: name'></span>uses the "active" template!</li> 4 </script> 5 <script id="inactive" type='text/html'> 6 <li><span data-bind='text: name'></span>uses the "inactive" template!</li> 7 </script> 8 9 <script> 10 var viewModel = { 11 employees: ko.observableArray([{ 12 name: "Kari", 13 active: ko.observable(true) 14 }, { 15 name: "Brynn", 16 active: ko.observable(false) 17 }, { 18 name: "Nora", 19 active: ko.observable(false) 20 }]), 21 displayMode: function(employee) { 22 // Initially "Kari" uses the "active" template, while the others use "inactive" 23 return employee.active() ? "active" : "inactive"; 24 } 25 }; 26 // ... then later ... 27 viewModel.employees()[1].active(true); 28 // Now "Brynn" is also rendered using the "active" template. 29 ko.applyBindings(viewModel); 30 </script>
上面這個例子有 active 和 inactive 兩個模板,ul 元素的 name 沒有直接指定模板 id ,而是經過一個函數返回模板 id,達到了選擇不一樣模板的目的。
吐槽一下:官方的文檔至關省,模板腳本都省掉了。。。博客園的湯姆大叔,竟然也就那樣搬下來了,純翻譯的讓人無語。
模板技術能夠簡單地將數據和表現分離,採用前端渲染技術時,後臺只要將模型數據發給客戶端便可,前端將獲取到的數據渲染輸出。目前爲止都是手動將獲取到的數據寫入 ViewModel 中,而 Mapping 插件就是幫你自動完成建立 ViewModel 的好工具。對比一下手動建立和使用 Mapping 插件兩種方式:
手動建立:
1 // setup 2 var viewModel = { 3 serverTime: ko.observable(), 4 numUsers: ko.observable() 5 } 6 // update: 7 var data = getDataUsingAjax(); // your method to get data from server 8 viewModel.serverTime(data.serverTime); 9 viewModel.numUsers(data.numUsers);
Mapping插件
1 var data = getDataUsingAjax(); // your method to get data from server 2 var viewModel = ko.mapping.fromJS(data); 3 ko.mapping.fromJS(data, viewModel);
假如從服務器中獲取的數據比較多的話,使用Mapping的確能夠減小不少代碼量。使用Mapping以後,data對象的全部屬性都被設置成可觀察對象,全部數組都被設置成可觀察對象數組,數組中的順序依然被保存。改變data對象的屬性或者增減數組項目就能夠引發綁定更新事件。Mapping插件還有不少高級用法,不過除非非Mapping插件不可的狀況,不必對一個插件投入太多精力去學習,搞太多還不如手寫算了。
本篇主要簡單介紹了knockoutjs中模板技術的使用,感受 ko 中用到的技術應該也差很少就這些了,自定義綁定和組件綁定相關的內容暫時沒有用到就不去深究了。組件的寫法有不少種,不必定要用 ko 的組件封裝規則,各有所好。 下一篇將會用一個綜合實例來介紹 ko 的各類綁定用法,敬請期待~~
碼字不易,隨手點贊哈~~~
參考資料:
文字較多,慣例湊圖!
(圖片來源:網絡)
原創文章,轉載請註明出處!本文連接:http://www.cnblogs.com/qieguo/p/5579888.html