KnockoutJs學習筆記(六)

這篇文章主要涉及control flow部分的binding。html


 

foreach binding主要做用於lists或是tables內數據單元的動態綁定。下面是一個簡單的例子:node

js部分:jquery

1 ko.applyBindings({
2   people: [
3     { firstName: "Chiaki", lastName: "Izumi" },
4     { firstName: "Kazusa", lastName: "Touma" },
5     { firstName: "Haruki", lastName: "Murakami" }
6   ]
7 });

html部分:git

 1 <table>
 2   <thead>
 3     <tr>
 4       <th>First Name</th>
 5       <th>Last Name</th>
 6     </tr>
 7   </thead>
 8   <tbody data-bind="foreach: people">
 9     <tr>
10       <td data-bind="text: firstName"></td>
11       <td data-bind="text: lastName"></td>
12     </tr>
13   </tbody>
14 </table>

頁面顯示效果以下:github

這裏的一個疑問在於如何利用thead顯示一列標題,留做之後研究數組

在上述示例中,咱們簡單的在ko.applybindings中添加了一個數組並將其綁定在一個tbody元素中,咱們也能夠自定義一個view model來實現這一效果,下面是一個更爲複雜一些的例子:app

js部分:less

 1 function MyViewModel() {
 2   var self = this;
 3 
 4   self.people = ko.observableArray([
 5     { name: "Chiaki" },
 6     { name: "Yuki" },
 7     { name: "Kazusa" }
 8   ]);
 9 
10   self.addPerson = function() {
11     self.people.push({ name: "New name at " + new Date() });
12   };
13 
14   self.removePerson = function() {
15     self.people.remove(this);
16   };
17 }
18 
19 ko.applyBindings(new MyViewModel());

html部分:ide

1 <h4>People</h4>
2 <ul data-bind="foreach: people">
3   <li>
4     Person at position <span data-bind="text: $index"></span>:
5     <span data-bind="text: name"></span>
6     <a href="#" data-bind="click: $parent.removePerson">Remove</a>
7   </li>
8 </ul>
9 <button data-bind="click: addPerson">Add</button>

顯示的效果以下:函數

因爲這裏並不支持添加script,不可以動態地顯示頁面。

注意一:以上的兩個例子中,在每一個foreach binding內部,咱們均可以直接調用綁定的數組內每一項的屬性,好比firstName和lastName,對於綁定的數組自己,也是能夠經過使用$data來調用。這就意味着$data.firstName和firstName的效果是同樣的,固然,前者勢必會顯得更爲冗餘。

注意二:在第二個例子中,咱們使用了$index來表示綁定的數組中每一項的索引,$index是一個observable,每當綁定的數組中的元素索引產生變化時,UI便會對相應的$index進行更新。另外,咱們也能經過$parent來獲取foreach外部的數據。有關$index和$parent的更爲詳盡的內容,可參考binding context properties,留做之後研究

注意三:在注意一中提到,咱們可以經過$data來調用foreach綁定的數組自己,可是當咱們使用嵌套的foreach,內層foreach如何可以調用外層foreach綁定的數組呢?這時咱們能夠藉由as給外層foreach所綁定的數組定義一個另外的名稱,進而在內層foreach中利用此名稱來調用外層foreach所綁定的數組。接下來是一個簡單的例子:

js部分:

1 var viewModel = {
2   person: ko.observableArray([
3     { name: "Chiaki", friends: [ "Charlie", "Kazusa" ] },
4     { name: "Kazusa", friends: [ "Chiaki", "Charlie" ] },
5     { name: "Charlie", friends: [ "Chiaki", "Kazusa" ] }
6   ])
7 };
8 
9 ko.applyBindings(viewModel);

html部分:

 1 <ul data-bind="foreach: { data: person, as: 'person' }">
 2   <li>
 3     <ul data-bind="foreach: { data: friends, as: 'friends' }">
 4       <li>
 5         <span data-bind="text: person.name"></span>:
 6         <span data-bind="text: friends"></span>
 7       </li>
 8     </ul>
 9   </li>
10 </ul>

頁面顯示效果以下:

這個例子中的外層foreach綁定的是person數組,person數組中有一個屬性name和另一個數組firends,在內層foreach中綁定的是數組firends。當咱們在內層foreach要調用外層的person數組內的屬性時,藉由as,使用了person.name來調用。而這裏也有一個有趣的狀況,就是當一個數組裏面只有單純的元素,好比說friends數組,它的元素並非object,也就不存在這identifier的問題,這時咱們要調用它的元素時,只須要調用數組自己便可,這也就是爲何在以前的示例中若是咱們調用綁定的數組自己會返回[object, object]。這代表,通常狀況下,遍歷數組中的元素只須要調用數組名(as指定)或是調用$data便可,而碰到那些內部元素是object的時候,咱們要調用object內的屬性則須要調用相應屬性的名稱

另外須要注意的一點就是,as後所跟着的必須是一個字符串(as: "person"而不是as: person)。

注意四:有些狀況下,咱們使用foreach的場合會比較複雜,好比說以下的例子:

1 <ul>
2   <li>Header item</li>
3   <!-- The following are generated dynamically from an array -->
4   <li>Item A</li>
5   <li>Item B</li>
6   <li>Item C</li>
7 </ul>

這種狀況下,咱們並不知道改在哪一個元素內添加foreach。若是是在ul添加的話,咱們事先寫好的header item便會被覆蓋掉,而ul元素內又只能嵌套li元素,添加另外一個容器來實現foreach也是不可行的。爲了解決這一問題,咱們須要使用無容器的控制流語法(containerless control flow syntax),與先前所提到的containerless text syntax相似。一個簡單的例子以下:

js部分:

1 var viewModel = {
2     people: ko.observableArray([
3         "Kazusa",
4         "Chiaki",
5         "Yuki"
6     ])
7 };
8 
9 ko.applyBindings(viewModel);

html部分:

1 <ul>
2     <li>Header item</li>
3     <!-- ko foreach: people -->
4     <li>name: <span data-bind="text: $data"></span></li>
5     <!-- /ko -->
6 </ul>

頁面顯示效果以下:

官方文檔中的注意五涉及到更改所綁定的數組時的性能問題,注意六主要涉及到destroyed的數組,這部分留做以後研究

注意七:當咱們須要在生成的DOM元素上運行一些自定義的邏輯時,咱們能夠用到afterRender/afterAdd/beforeRemove/beforeMove/afterMove等回調函數。

須要注意的是,這些回調函數僅僅適用於觸發與列表的改變有關的動畫,若是咱們須要對新添加的DOM元素附加一些其餘的行爲,好比說事件的處理或是第三方的UI控制,將這些行爲做爲自定義的綁定(custom binding)會更爲合適,由於這樣設定的行爲是與foreach互相獨立的。

接下來是一個調用afterAdd的簡單的例子,其中用到了jQuery Color plugin

js部分:

 1 var viewModel = {
 2     people: ko.observableArray([
 3         "Kazusa",
 4         "Chiaki",
 5         "Yuki"
 6     ]),
 7     
 8     yellowFadeIn: function(element, index, data) {
 9         $(element).filter("li")
10               .animate({ backgroundColor: "yellow" }, 200)
11               .animate({ backgroundColor: "white" }, 800);
12     },
13 
14     addItem: function() { this.people.push("New person"); }
15 };
16 
17 ko.applyBindings(viewModel);

我對這裏的this的使用是有疑問的,聯想到computed observable內this的使用,留做以後研究

html部分:

1 <ul data-bind="foreach: { data: people, afterAdd: yellowFadeIn }">
2     <li data-bind="text: $data"></li>
3 </ul>
4 
5 <button data-bind="click: addItem">Add</button>

因爲我還沒掌握製做和插入動態圖片的方式,這裏不展現顯示的效果,不過在點擊Add button以後,New person會被添加,通知其背景顏色又黃色變爲白色。

如下是對一些回調函數詳盡的介紹:

afterRender是在foreach模塊初始化或是添加新的元素時觸發的,其接受的參數爲(爲了可以保持願意,這裏用英文顯示,下同):

  1. An array of the inserted DOM elements
  2. The data item against which they are being bound

afterAdd與afterRender相似,不過它只會在新元素添加時觸發(foreach初始化的時候並不會觸發),它所接受的參數爲:

  1. A DOM node being added to the document
  2. The index of the added array element
  3. The added array element

beforeRemove函數會在數組中的某一項被刪除時觸發。須要注意的是,beforeRemove實際上替代了UI界面對remove所作出的迴應,即在beforeRemove函數中若是不對DOM相應的元素進行remove操做,則在頁面上的元素是不會被刪除的,可是viewModel中的數組相應的元素卻已經被刪除了。beforeRemove函數接受如下參數:

  1. A DOM node that you should remove
  2. The index of the removed array element
  3. The removed array element

beforeMove函數會在數組中的元素索引起生變化時觸發,beforeMove會應用於全部索引產生變化的元素,即倘若咱們在數組開頭插入元素,則其後全部元素都將受到beforeMove回調函數的影響。一個比較經常使用的作法是經過beforeMove來保存原有元素的座標以便咱們可以在afterMove中控制元素移動的動畫。beforeMove函數接受如下參數:

  1. A DOM node that may be about to move
  2. The index of the moved array element
  3. The moved array element

afterMove函數也會在數組中的元素索引起生變化時觸發,afterMove會應用於全部索引產生變化的元素,即倘若咱們在數組開頭插入元素,則其後全部元素都將受到afterMove回調函數的影響。afterMove函數接收如下參數:

  1. A DOM node that may have moved
  2. The index of the moved array element
  3. The moved array element

對於回調函數中的before和after,咱們應該有一個比較清醒的認識。before和after針對的都是UI界面中的元素變化,也就是頁面產生變化以前和頁面產生變化以後,與此同時,viewModel部分的數組已經發生了變化,正是viewModel部分的數組的變化才觸發了before和after所對應的回調函數。

相關文章
相關標籤/搜索