knockoutJS學習筆記06:ko數組與模板綁定


  前面已經介紹了基本的綁定和模板相關知識,接下來就看ko里的數組和模板綁定,數組和模板綁定應該是實際項目中用得比較多的,ko提供了很好的支持。

一、observaleArray

  前面的監控屬性都是單個對象,用的是ko.observable;有時候后台返回的是一個列表,也就是數組,這個時候就需要用監控數組了。監控數組與監控屬性幾乎一樣,只不過它是一個數組對象,擁有數組的特點。例如:創建一個簡單的監控數組:

  var arr = ko.observableArray();

  也可以開始就進行初始化:  

  arr = ko.observableArray([1,2,3]);

   普通數組獲取長度就是 arr.length,而監控數組與監控屬性一樣,需要用方法,例如:arr().length

二、監控數組常見方法

  監控數組擁有普通數組的所有方法,用法也基本一樣。

  2.1 push 增加一個新元素

    arr.push(4);  

  2.2 pop 刪除一個元素,並返回這個元素

    var v = arr.pop();

  2.3 shift 在開始處刪除一個元素,並返回這個元素

    var v = arr.shift();

  2.4 unshift 在開始處增加一個元素

    arr.unshift(0);

  2.5 reverse 反轉數組

    arr.reverse();

  2.6 sort 數組排序

    arr.sort();

  可以看到,上面的方法和js里的數組方法一模一樣,用法也是一樣的。此外,ko還支持另外兩個方法,remove 和 removeAll:

    remove:移除指定元素或移除指定條件的元素。如:arr.remove(1); 或者 arr.remove(function(item){return item > 1;});

    removeAll:移除指定的元素集或移除所有元素。如:arr.removeAll([1,2]); 或者 arr.removeAll();

  上面數組的內容只是簡單的數據類型,實際也可以復雜的類型。需要注意的是,為了提高性能,監控數組只監控數組對象,而不監控數組元素對象的屬性。也就是說,如果arr元素是對象,那么對arr進行的操作會反應到UI(反之也會);但對arr[0]對象內部的屬性的操作,就不會反應到UI(反之也不會)。

二、foreach 綁定

  既然是數組,自然就需要遍歷輸出了。foreach 綁定就是用來遍歷集合的,如果集合是空的,會在頁面上留下一個空的模板。

  2.1 foreach指定要遍歷的屬性,內部的結構會自動循環綁定。例如:

    <div data-bind="foreach:list">
        <p>姓名:<span data-bind="text:name"></span>,年齡:<span data-bind="text:age"></span></p>
    </div>

   2.2 通過 as 關鍵字為遍歷的屬性定義別名,這樣就可以通過別名對它進行訪問。

    <ul data-bind="foreach:{data:data,as:'data'}">
        <li>
            <p data-bind="text:name"></p>
            <ul data-bind="foreach:{data:contains,as:'item'}">
                <li>
                    <p><span data-bind="text:item.name"></span>屬於<span data-bind="text:data.name"></span></p>
                </li>
            </ul>
        </li>
    </ul>
    var data = [
        {name:"水果",contains:[{name:"蘋果",work:"蘋果的作用"},{name:"香蕉",work:"香蕉的作用"}]},
        {name:"蔬菜",contains:[{name:"青菜",work:"青菜的作用"},{name:"白菜",word:"白菜的作用"}]}
    ];     
    ko.applyBindings(data);

  這里要注意,as后面的名稱必須加引號。在ko里,凡是作為名稱的,都必須加引號,而如果作為對象或者屬性的,就不需要。

三、ko 模板綁定

  ko 的模板用template指定,template 可以直接指定模板名稱,也支持更多選項。

  3.1 直接指定模板名稱

<div data-bind="template:'tmpl'"></div>

  3.2 templdate 支持更多的選項,讓我們可以更靈活的控制整個渲染過程。

    name(必選項) — 需要render的模板ID。

    data(可選項) — 需要render到模板的數據。如果你忽略整個參數,KO將查找foreach參數,或者是應用整個view model對象。

    foreach(可選項) — 指定KO按照“foreach”模式render模板。

    afterAdd或beforeRemove(可選項) — 在foreach模式下使用callback函數。

    templateOptions(可選項) — 在render模板的時候,傳遞額外數據以便使用。

<div data-bind="template:{name:'koPersonList',foreach:list}"></div>
<script type="text/tmpl" id="koPersonList">
    <p>姓名:<span data-bind="text:name"></span>,年齡:<span data-bind="text:age"></span></p>
</script>

    另外,template里的name 屬性不只可以寫死為一個模板名稱,還可以是一個方法屬性,由它來動態決定使用哪個模板。例如下面的例子,在遍歷的時候,會根據名稱來決定使用哪個模板。   

       <div data-bind="template:{name:display,foreach:list}"></div>
        this.display = function(item){
            if(item.name() === "tom1"){
                return "tmpl1";//使用模板1渲染
            }
            return "tmpl2";//使用模板2渲染
        }

三、結合jqtmpl

  集合類型通常要進行遍歷渲染,之前我們已經寫過模板引擎了,也介紹了jsRender,都支持循環遍歷。ko 默認支持的jqtmpl模板。簡單介紹一下jqtmpl,它的 tag 有:

  ${變量} : 輸出變量值

  ${{html 變量}} :輸入變量html

  ${{if condition}}...${{else condition}}...${{else}}...${{/if}} :if-else 判斷

  ${{each(index,item) 集合}...${{/each}} :遍歷

  可以看出,jqtmpl和jsRender的結構是非常像。我們用template集合jqtmpl看兩個例子。 

  例子1:

<div data-bind="template:'person'"></div>
<script type="text/tmpl" id="person">
    <p>姓名:${name},年齡:${age}</p>
</script>:    

  例子2:

    <div id="" data-bind="template:{name:'personList',foreach:list}"></div>
    <script type="text/tmpl" id="personList">
        <p>姓名:${name},年齡:${age}</p>
    </script>
    function Person(name,age){
        this.name = name;
        this.age = age;
    }    
    function ViewModel(){
        this.list = [
            new Person("tom",18),
            new Person("jack",20),
            new Person("lucy",22)];
    }
    ko.applyBindings(new ViewModel());   

  注意:和jqtmpl一起使用時,ko.js必須先引入,后再引入jqtmpl.js,否則會沒有效果。

  上面的例子就是把ko的輸出方式,換成jqtmpl的輸出方式,結果是一樣的。那么使用<span data-bind="text:someObservableValue"></span> 與 ${someObservableValue} 有什么區別呢?

  當模板內部使用data-bind屬性的時候,KO是單獨為這個綁定單獨跟蹤依賴項的。當model改變的時候,KO只會更新綁定的元素以及子元素而不需要重新render整個模板。所以如果你聲明這樣的代碼是<span data-bind='text: someObservableValue'></span>,當 someObservableValue改變的時候,KO將只是簡單地更新<span>元素的text值而不需要重新render整個模板。

  不過,如果模板內部使用的observable值(例如${ someObservableValue }),如果這個observable值改變了,那KO將重新render整個模板(這往往不是我們想要的)。

  這就是說,很多情況下<span data-bind='text: someObservableValue'></span>性能要比${ someObservableValue }要好,因為值改變的話不會影響臨近元素的狀態。不過${ someObservableValue }語法比較簡潔,如果你的模板比較小的話,還是更合適的,不會帶來大的性能問題。

五、用ko模板完成開篇的demo

  開篇我們用了多種方式完成一個簡單的demo,這樣用ko來完成相同的功能。

  html:  

    <div id="main">
        <div id="title">所有課程</div>
        <ul id="course" data-bind="template:{name:'courseTmpl',foreach:courseList}"></ul>
    </div>

   模板:

<script type="text/tmpl" id="courseTmpl">
    <li>
        <a data-bind="attr:{href:'Default.aspx?courseID='+CourseID}">
            <div class="course-img">
                <img data-bind="attr:{src:IconPath,alt:CourseName}"/>
            </div>
            <div class="course-info">
                <div class="names">
                    <span data-bind="text:CourseName"></span>
                    <span data-bind="text:TeacherName" class="fr"></span>
                </div>
                <div class="pros">
                    <span data-bind="text:CreatedDate"></span>
                    <span class="fr"><span data-bind="text:StudyNumber"></span>人學習</span>
                </div>
            </div>
        </a>
    </li>
</script>

   js:

    function CourseInfoVM(){
        var self = this;
        this.courseList = ko.observableArray();
    }
    var courseInfoVM = new CourseInfoVM();
    ko.applyBindings(courseInfoVM,document.getElementById("course"));
    window.Tester.callback(function(data){          
          courseInfoVM.courseList(data);
    })

 六、總結

  ko的模板綁定提供了很多的功能和支持,讓我們對集合類型的處理更加方便,頁面的結構更加清晰,腳本更加簡潔。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM