KnockoutJS-模板綁定

  對於knockoutJS來說,模板綁定和Mapping插件綁定是十分重要的功能,雖然模板綁定在我工做中用的及其少,但模板綁定的重要性不可忽視,在其餘前端框架中,如Angular、Vue等等,模板存在的意義十分重要,Mapping插件使得咱們可以脫離手工綁定,及其方便咱們快速綁定達到預期效果。javascript

  KnockoutJS模板綁定更多用法:https://knockoutjs.com/documentation/template-binding.htmlphp

 

1、模板綁定目的

  在mvc的開發中,對於經常使用的一些獨立的Html,習慣將它變成分佈視圖或是視圖組件,以此來方便調用以及重用,同時也達到解耦效果,一樣在前端開發中,對於部分重用度很高、複雜度高的UI、嵌套UI等這些部分,咱們也能夠設計成模板。html

  

  在knockoutJS中經過template綁定將模板綁定到預期DOM元素中,將模板所依賴的數據呈現。模板綁定對於構建嵌套結構的頁面十分方便,默認狀況, Knockout使用jquery.tmpl模板引擎,使用模板綁定時,需引用jquery.tmpl和jQuery框架,或者你也能夠集成其它的模板引擎(須要瞭解Knockout 內部知識)。前端

  模板語法:java

  • ${ someValue } 
  • {{html someValue}}
  • {{if someCondition}}
  • {{else someCondition}}
  • {{each someArray}}

  具體瞭解模板語法能夠查看:http://www.php.cn/js-tutorial-383558.htmljquery

 

2、模板綁定應用

   若是你僅僅是聲明的字符串,KO將會使用它做爲模板的ID去渲染。應用在模板上的數據是你當前的viewModel對象。git

  一、構建一個簡單模板api

<hr />
<label>標準模板</label>
<div data-bind="template: 'personTemplate'"></div>
<script id='personTemplate' type='text/html'>
    ${ name } 是 ${ age } 歲
    <button class="btn btn-primary" data-bind='click: makeOlder'>增加一歲</button>
</script>

@section Scripts{
    <script type='text/javascript'>
        var viewModel = {
            name: ko.observable('刺客'),
            age: ko.observable(20),
            makeOlder: function () {
                viewModel.age(viewModel.age() + 1);
            }
        };

        $(function () {
            ko.applyBindings(viewModel);
        })
    </script>
}

  經過設計一個簡單的模板,在viewModel中的name或age發生改變後,Knockout將自動從新render模板。在該例子裏,每次點擊按鈕都會從新渲染該模板。數組

  二、構建一個性能更好點的簡單模板前端框架

<br /><hr />
<label>加強版</label>
<div data-bind="template: 'personAdvancedTemplate'"></div>
<script id='personAdvancedTemplate' type='text/html'>
    <label data-bind="text:name()+'是'+age()+'歲'"></label>
    <button class="btn btn-primary" data-bind='click: makeOlder'>增加一歲</button>
</script>

@section Scripts{
    <script type='text/javascript'>
        var viewModel = {
            name: ko.observable('刺客'),
            age: ko.observable(20),
            makeOlder: function () {
                viewModel.age(viewModel.age() + 1);
            }
        };

        $(function () {
            ko.applyBindings(viewModel);
        })
    </script>
}

  經過data-bind的形式將屬性綁定時,若是屬性改變了,將直接改變值,而無需從新渲染模板,這比經過${property}方式更加高效點,可是若是說模板內容較小較簡單,直接使用${property}這種方式也是可行的,浪費點性能,寫起來快捷方便。

  三、嵌套模板

<br /><hr />
<label>嵌套模版</label>
<div data-bind="template: 'firstPersonAdvancedTemplate'"></div>
<script id='firstPersonAdvancedTemplate' type='text/html'>
    <label data-bind="text:name()+'是'+age()+'歲'"></label>
    <button class="btn btn-primary" data-bind='click: makeOlder'>增加一歲</button>
    <div style="border:1px dotted red;" data-bind="template: 'secondPersonAdvancedTemplate'"></div>
</script>
<script id='secondPersonAdvancedTemplate' type='text/html'>
    <label data-bind="text:name()+'是'+age()+'歲'"></label>
    <button class="btn btn-primary" data-bind='click: makeOlder'>增加一歲</button>
</script>
@section Scripts{
    <script type='text/javascript'>
        var viewModel = {
            name: ko.observable('刺客'),
            age: ko.observable(20),
            makeOlder: function () {
                viewModel.age(viewModel.age() + 1);
            }
        };

        $(function () {
            ko.applyBindings(viewModel);
        })
    </script>
}

  效果:

  

  嵌套模板是在一個模板的基礎上,在模板中繼續使用data-bind的形式利用template嵌套其餘模板,模板的從新渲染以就近原則爲主,最近的模板數據改變,只渲染最近的模板,對於全部的模板不進行從新渲染。

  四、foreach模板

  在模板中使用foreach完成相應的循環顯示時,有兩種方式,一種使用模板語法{{each personArray}}這種形式 ,可是這種在性能上不如直接使用data-bind的方式,所以我將直接使用data-bind完成foreach模板綁定,

<br /><hr />
<label>foreach模板</label>
<ul data-bind="template: { name: 'dynastyForeachTemplate',foreach: dynastys,afterAdd:afterAddFunc,beforeRemove:beforeRemoveFunc }"></ul>
<script id='dynastyForeachTemplate' type='text/html'>
    <li><label data-bind="text:dynastyName()+'是'+dynastyAge()+'年'"></label></li>
</script>
@section Scripts{
    <script type='text/javascript'>
        function dynastyViewModel(name, age) {
            dynastyName = ko.observable(name);
            dynastyAge = ko.observable(age);
        }

        var viewModel = {
            dynastys: ko.observableArray([new dynastyViewModel("秦朝", 30)]),
            afterAddFunc: function () {
                console.log("afterAddFunc");
            },
            beforeRemoveFunc: function () {
                console.log("beforeRemoveFunc");
            },
            addDynasty: function () {
                console.log("addDynasty");
                viewModel.dynastys.push(new dynastyViewModel("", 0));
            },
            deleteDynasty: function (dynasty) {
                console.log("deleteDynasty");
                viewModel.dynastys.remove(dynasty);
            }
        };

        $(function () {
            ko.applyBindings(viewModel);
            viewModel.dynastys.push(new dynastyViewModel("唐朝", 300));
            viewModel.dynastys.push(new dynastyViewModel("宋朝", 300));
            viewModel.dynastys.push(new dynastyViewModel("元代", 300));
        })
    </script>
}

  

  對於複雜的模板來說,須要循環使用如跟帖回帖操做,只有內容不一樣、時間不一樣等等,其餘html元素是同樣的,則使用這種方式能大幅提升開發效率。當增長一個Item到fo'reach關聯的數組集合中時,只會將Item部分進行模板的從新渲染,其他已有的部分不影響,

當刪除Item項時,模板不執行渲染,只是將Item從集合中移除。

  五、table模板

<br /><hr />
<label>table模板</label>
<table class="table table-bordered">
    <thead>
        <tr>
            <th>朝代</th>
            <th>存活時間</th>
            <th></th>
        </tr>
    </thead>
    <tbody data-bind="template:  { name: 'dynastyTableTemplate', foreach: dynastys,afterAdd:afterAddFunc,beforeRemove:beforeRemoveFunc }"></tbody>
    <tfoot>
        <tr>
            <td colspan="3" class="text-center"><button class="btn btn-primary" data-bind="click:addDynasty">增長朝代</button></td>
        </tr>
    </tfoot>
</table>
<script id='dynastyTableTemplate' type='text/html'>
    <tr>
        <td><input data-bind="value:dynastyName" /></td>
        <td><input data-bind="value:dynastyAge" /></td>
        <td><button class="btn btn-danger" data-bind="click:$root.deleteDynasty">刪除</button></td>
    </tr>
</script>

@section Scripts{
    <script type='text/javascript'>
        function dynastyViewModel(name, age) {
            dynastyName = ko.observable(name);
            dynastyAge = ko.observable(age);
        }

        var viewModel = {
            dynastys: ko.observableArray([new dynastyViewModel("秦朝", 30)]),
            afterAddFunc: function () {
                console.log("afterAddFunc");
            },
            beforeRemoveFunc: function () {
                console.log("beforeRemoveFunc");
            },
            addDynasty: function () {
                console.log("addDynasty");
                viewModel.dynastys.push(new dynastyViewModel("", 0));
            },
            deleteDynasty: function (dynasty) {
                console.log("deleteDynasty");
                viewModel.dynastys.remove(dynasty);
            }
        };

        $(function () {
            ko.applyBindings(viewModel);
            viewModel.dynastys.push(new dynastyViewModel("唐朝", 300));
            viewModel.dynastys.push(new dynastyViewModel("宋朝", 300));
            viewModel.dynastys.push(new dynastyViewModel("元代", 300));
        })
    </script>
}

  對於table模板的實際用法與foreach模板是同樣的,在foreach模板中也一樣能夠看見table模板的效果展現。

 

  data-bind下template的綁定參數有

            name(必選項) — 須要render的模板ID,能夠經過對綁定屬性中值的動態變換,切換不一樣的模板使用。

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

            foreach(可選項)— 指定KO按照「foreach」模式render模板 

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

            templateOptions(可選項) — 在渲染模板時可傳遞額外數據以便使用,可幫助你使用一些不屬於viewModel過濾條件或者字符來重用模板。

 

  固然還有其餘模板引擎可使用,可是就目前來說,我的感受jquery.tmpl引擎已經知足個人需求了。

  本文地址:http://www.javashuo.com/article/p-xsvtroit-dn.html 

  本文demo地址:https://gitee.com/530521314/koInstance.git

 

2018-10-13,望技術有成後能回來看見本身的腳步
相關文章
相關標籤/搜索