KnockOut 綁定之foreach綁定(mvc+knockout)

何時使用foreach綁定

foreach綁定對於數組中的每個元素複製一節標記語言,也就是html,而且將這節標記語言和數組裏面的每個元素綁定。當咱們呈現一組list數據,或者一個表格的時候,十分有用。javascript

若是你綁定的數組是一個"監控數組" ,observable array,(和wpf裏面的ObservableCollection<T>差很少)。當你添加或移除,或者從新排序數組裏面的元素的時候,會動態的更新UI界面。而且此時並不會影響原先的DOM元素。這樣比咱們直接從新生成一個數組而且綁定元素高效的多。html

固然,foreach也支持嵌套綁定,或者和其餘工做流綁定例如if 或者with。java

Example 1: 迭代綁定一個數組

對數組中的每個元素生成一行數據的只讀表。jquery

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

<table>
    <thead>
        <tr><th>First name</th><th>Last name</th></tr>
    </thead>
    <tbody data-bind="foreach: people">
        <tr>
            <td data-bind="text: firstName"></td>
            <td data-bind="text: lastName"></td>
        </tr>
    </tbody>
</table>

<script type="text/javascript">
    ko.applyBindings({
        people: [
            { firstName: 'Bert', lastName: 'Bertington' },
            { firstName: 'Charles', lastName: 'Charlesforth' },
            { firstName: 'Denise', lastName: 'Dentiste' }
        ]
    });
</script>

效果以下:數組

First name Last name
Bert Bertington
Charles Charlesforth
Denise Dentiste

 

 

 

 

Example 2: 給例1中的制度表加上一個增長和移除方法

下面這個例子展現了,若是你綁定的數組是一個監控數組,那麼這個UI界面將會和數組的改變同步。app

People

  • Name at position 0: Bert Remove
  • Name at position 1: Charles Remove
  • Name at position 2: Denise Remove

dom

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

<h4>People</h4>
<ul data-bind="foreach: people">
    <li>
        Name at position <span data-bind="text: $index"> </span>:
        <span data-bind="text: name"> </span>
        <a href="#" data-bind="click: $parent.removePerson">Remove</a>
    </li>
</ul>
<button data-bind="click: addPerson">Add</button>

<script type="text/javascript">
    function AppViewModel() {
        var self = this;

        self.people = ko.observableArray([
            { name: 'Bert' },
            { name: 'Charles' },
            { name: 'Denise' }
        ]);

        self.addPerson = function () {
            self.people.push({ name: "New at " + new Date() });
        };

        self.removePerson = function () {
            self.people.remove(this);
        }
    }

    ko.applyBindings(new AppViewModel());
</script>

參數

    • 主參數函數

    • 給foreach傳過去你但願迭代的數組。對於每個數組元素foreach綁定會輸出一段超文本標記語言。post

    • 你也能夠給foreach綁定傳遞一個含有data屬性的 的你想要去迭代的javascript字面量,這個字面量也能夠有其它屬性, 例如 afterAdd 或者includeDestroyed ,能夠看接下來的例子。優化

    • 若是你綁定的是一個監控數組,對數組內容的增長或者移除foreach綁定將會在UI界面上增長或者移除dom元素。

    • 其它參數

要點1:  用 $data來指向數組的每一條數據

就像在上面的例子中展現的。foreach綁定可以指向數組每一條數據的屬性。例如例1中的firstName 和lastName.可是,若是咱們想指向數組自己,應該怎麼辦,此時咱們能夠用$.data.在foreach綁定中,$data指的就是數組的當前的元素項。

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>
<ul data-bind="foreach: months">
    <li>
        The current item is: <b data-bind="text: $data"></b>
    </li>
</ul>

<script type="text/javascript">
    ko.applyBindings({
        months: ['Jan', 'Feb', 'Mar', 'etc']
    });
</script>

效果以下

  • The current item is: Jan
  • The current item is: Feb
  • The current item is: Mar
  • The current item is: etc

固然,若是你非要這樣作的話, 你也能夠給你指向的每個屬性加上一個 $data前綴.例如,你也能夠在例1中像下面這樣寫,雖然這樣寫不必,由於它的默認上下文就是$data:

<td data-bind= "text: $data.firstName" ></td>

 

要點 2: 使用$index, $parent, 和其餘的上下文屬性

就像咱們在例2 中看到的那樣。你可一用$index 來表示數組中當前項從零開始的索引。 $index是一個監控屬性,當數組的項變動的時候$index也會自動更新。

一樣,你也能夠用$parent來指向foreach外的數據。若是foreach對應的是viewmodel的直接子元素,那麼$parent就是指的viewmodel

<h1 data-bind="text: blogPostTitle"></h1>
<ul data-bind="foreach: likes">
    <li>
        <b data-bind="text: name"></b> likes the blog post <b data-bind="text: $parent.blogPostTitle"></b>
    </li>
</ul>

更多關於 $index和$parent的資料能夠去看 binding context properties.

要點 3: 用as 給foreach項賦值一個別名

就想在要點1裏面描述的那樣。咱們能夠引用每個數組項用  $data 上下文變量。但在一些特殊狀況下,給當前項一個別名用起來更方便。尤爲在多層嵌套結構中:

別名使用的語法以下:

<ul data-bind="foreach: { data: people, as: 'person' }"></ul>

如今在foreach循環的任何地方,綁定均可以根據person指向當前people的數組項。這種語法在多層foreach嵌套的場景中很是有用。例如:

<ul data-bind="foreach: { data: categories, as: 'category' }">
    <li>
        <ul data-bind="foreach: { data: items, as: 'item' }">
            <li>
                <span data-bind="text: category.name"></span>:
                <span data-bind="text: item"></span>
            </li>
        </ul>
    </li>
</ul>
 
<script>
    var viewModel = {
        categories: ko.observableArray([
            { name: 'Fruit', items: [ 'Apple', 'Orange', 'Banana' ] },
            { name: 'Vegetables', items: [ 'Celery', 'Corn', 'Spinach' ] }
        ])
    };
    ko.applyBindings(viewModel);
</script>

注意: 記得經過as給別名 賦值的時候,傳過去一個字符串'category', 不是as: category), 由於咱們是要給變量起一個別名,而不是傳遞一個標識符變量過去。

Note 4: 沒有一個容器元素的時候使用foreach

在一些狀況下,你想要經過foreach綁定一段標記語言html,可是沒有供foreach綁定的元素。例以下面這張情景:

<ul>
    <li class="header">Header item</li>
    <!-- The following are generated dynamically from an array -->
    <li>Item A</li>
    <li>Item B</li>
    <li>Item C</li>
</ul>

這種狀況下沒有任何元素可供foreach綁定。你不能放到ul裏面,由於這時候會把header也放到複製的循環裏面去。你也不能放其它的元素在ul裏面,由於ul裏面只容許放<li>元素。

要想處理這種狀況。咱們能夠用無容器綁定語法。這中狀況是依賴於html的註釋標籤。以下:

 

<ul>
    <li class="header">Header item</li>
    <!-- ko foreach: myItems -->
        <li>Item <span data-bind="text: $data"></span></li>
    <!-- /ko -->
</ul>
 
<script type="text/javascript">
    ko.applyBindings({
        myItems: [ 'A', 'B', 'C' ]
    });
</script>

<!-- ko --> 和 <!-- /ko --> 註釋做爲標籤的開始和結束,定義了一個虛元素來包含咱們須要重複引用的標記語言在裏面,knockout理解這種虛元素語法。咱們能夠就當真的有一個html元素來使用它。

要點 5: 數組的改變如何被檢測和處理

當你修改綁定煮熟的值時,例如增長刪除移動, foreach綁定用一個有效的區分語法來檢測出哪一項被改變了。因此,可以去改變預知匹配的dom元素,這覺得着knockout能夠處理任意的和並和同時的改變 

  • 當我麼增長一個數組項的時候, foreach 將會根據咱們的模板繪製一個新的dom元素想插入到原先的dom元素中。
  • 當咱們刪除一個項目的時候, foreach 將會移除相關的dom元素。
  • 當咱們移動相關的數組項時), foreach 將只會移動相關的dom元素。

注意,從新排列時候的排列不是確定的:須要確保咱們的元素想操做足夠快。,它被優化只是檢測少許的數組項變更。當同時變更的元素不少的時候,knockout會選擇執行刪除而後從新的添加的方式,而不是隻是移動dom元素。

要點 6: 刪除項默認被隱藏

有時你想要將一個數組項標記爲刪除, 但並非真的刪除. 這就是咱們所說的「非毀滅式刪除」. 對於更多的資料能夠看the destroy function on observableArray.

默認的foreach 綁定將會只是將被刪除的項隱藏。若是你想看並不是真正被刪除的項,你能夠用 includeDestroyed參數. 例如

<div data-bind='foreach: { data: myArray, includeDestroyed: true }'>
    ...
</div>

要點 7: dom元素後期處理或生成動畫

若是咱們想在生成dom元素的時候添加更多自定義的邏輯咱們能夠用,afterRender/afterAdd/beforeRemove/beforeMove/afterMove 這些回調函數

注意: 這些回調函數時爲了生成list改變的時候的動畫。對於一些跟複雜的需求,咱們能夠用自定義綁定 custom binding 。

@{
    Layout = null;
}
<script src="~/Scripts/jquery-1.10.2.js"></script>
<script src="~/Scripts/jquery.color-2.1.2.js"></script>
<script src="~/Scripts/knockout-3.2.0.js"></script>

<ul data-bind="foreach: { data: myItems, afterAdd: yellowFadeIn }">
    <li data-bind="text: $data"></li>
</ul>

<button data-bind="click: addItem">Add</button>

<script type="text/javascript">
    ko.applyBindings({
        myItems: ko.observableArray(['A', 'B', 'C']),
        yellowFadeIn: function (element, index, data) {
            $(element).filter("li")
                      .animate({ backgroundColor: 'yellow' }, 200)
                      .animate({ backgroundColor: 'white' }, 800);
        },
        addItem: function () { this.myItems.push('New item'); }
    });
</script>

效果以下

更多細節:

  • afterRender — 當foreach 模板元素被插入document 的時候被調用。第一次初始化和後續每次添加的時候都會調用這個回調函數。會傳遞下面的參數給回調函數:

    1. 插入的dom元素數組
    2. 被綁定的數據元素自己
  • afterAdd —和 afterRender很像,不過只有增長元素的時候被調用,第一次初始化的時候不會被調用.經常使用來執行元素的淡入$(domNode).fadeIn() 該函數接收下列參數:

    1. 增長的dom節點。
    2. 增長元素的索引
    3. 增長的數組元素
  • beforeRemove —當一個數組元素被移除,可是相關的dom元素尚未被移除的時候調用,.  a beforeRemove 經常使用來執行dom節點的淡出. $(domNode).fadeOut() 這種狀況下knockout不知道你要設置多久的淡出時間,因此對於元素的移除,要在該回調函數裏面手動移除。該函數接收如下參數:

    1. 應該被移除的數組節點
    2. 被移除數組元素的索引
    3. 移除的數組元素
  • beforeMove —當一個數組元素改變了位置,可是相關的dom元素尚未被移動的時候執行. 注意beforeMove 將會對全部索引改變的數組元素有效。 因此,若是你在數組元素的開始位置插入一項,那麼aftermove回調函數會對全部的元素有效。由於全部元素的索引都加1改變。咱們能夠用. beforeMove 來記錄爲移動前元素值,而後在aftermove中使用.該回調函數接收如下參數:

    1. 打算移動的dom節點
    2. 移動的數組元素的索引
    3. 移動的數組元素
  • afterMove —在數組元素的位置被改變後調用, 而且是在foreach更新了dom元素後調用 注意afterMove 將會對全部索引改變的數組元素有效。 因此,若是你在數組元素的開始位置插入一項,那麼aftermove回調函數會對全部的元素有效。由於全部元素的索引都加1改變。該回調函數接收如下參數:

    1. 一個已經被移除的dom 節點
    2. 移除數組元素的索引
    3. 移除的數組 元素

更多的例子afterAdd and beforeRemove 請看 animated transitions.

knockout分頁demo: http://www.cnblogs.com/santian/p/4342777.html

KnockOut官網:http://knockoutjs.com/documentation/foreach-binding.html

本文地址:http://www.cnblogs.com/santian/p/4379445.html

博客地址:一天兩天三天

轉載請以超連接形式標明文章原始出處。
相關文章
相關標籤/搜索