【Knockout.js 學習體驗之旅】(3)模板綁定

本文是【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.tmplUnderscore等模板引擎網絡

下面簡單講講ko中模板綁定的使用,第三方的集成引用不在本文討論範圍內。app

knockout.js 的模板綁定

先看一個例子:

  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數據。下面簡單說說模板綁定中用到的參數:

  • name — 指定你要渲染的模板片斷,跟模板腳本中的 id 相對應。
  • nodes — 直接傳遞一個DOM節點數組做爲模板使用。傳遞的DOM節點數列應該是不被監控的,由於渲染過程當中會對這個節點數列進行復制賦值等操做。並且若是這個節點數組有父級節點的話也會被移除。當咱們傳遞了一個非空的name值時,nodes選項會被忽略,因此不多會用到這個屬性。
  • data — 用來做爲渲染數據的對象。若是你忽略整個參數,KO將查找foreach參數,或者是應用整個view model對象。
  • if — 與上一篇中的 if 做用相似,只有當 if 後的表達式爲真時纔會渲染模板,用於防止一個空可觀察對象在模板被填充以前被綁定。
  • foreach — 按照「foreach」模式渲染模板。
  • as — 結合foreach使用的時候,指定每項渲染數據的別名,主要是用於定義數據範圍方便在嵌套綁定裏面使用。
  • afterRender, afterAdd, or beforeRemove — 渲染時的回調函數。

下面簡單簡單介紹一下幾種用法。

一些例子

  • 使用 foreach 渲染 ViewModel中的全部數據
  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>
  • as 在嵌套綁定中的使用
  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,達到了選擇不一樣模板的目的。

吐槽一下:官方的文檔至關省,模板腳本都省掉了。。。博客園的湯姆大叔,竟然也就那樣搬下來了,純翻譯的讓人無語。

Mapping插件

模板技術能夠簡單地將數據和表現分離,採用前端渲染技術時,後臺只要將模型數據發給客戶端便可,前端將獲取到的數據渲染輸出。目前爲止都是手動將獲取到的數據寫入 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 的各類綁定用法,敬請期待~~

碼字不易,隨手點贊哈~~~

 

參考資料:

  1. 官方教程: http://knockoutjs.com/documentation/introduction.html
  2. 湯姆大叔教程(官方教程翻譯,版本太舊,信息缺失明顯): http://www.cnblogs.com/TomXu/archive/2011/11/21/2257154.html
  3. 一個對前端模板技術的全面總結: http://www.tuicool.com/articles/qMJ77r

文字較多,慣例湊圖!

tibet-lake

(圖片來源:網絡)

原創文章,轉載請註明出處!本文連接:http://www.cnblogs.com/qieguo/p/5579888.html 

相關文章
相關標籤/搜索