Knockout应用开发指南 第四章:模板绑定

模板绑定The template binding

目的javascript

template绑定经过模板将数据render到页面。模板绑定对于构建嵌套结构的页面很是方便。默认状况, Knockout用的是流行的jquery.tmpl模板引擎。使用它的话,须要在安装页面下载和引用jquery.tmpl和jQuery框架。或者你也能够集成其它的模板引擎(虽然须要了解Knockout 内部知识才行)。css

 

例子html

<div data-bind='template: "personTemplate"'> </div>
<script id='personTemplate' type='text/html'>
${ name } is ${ age } years old
<button data-bind='click: makeOlder'>Make older</button>
</script>

<script type='text/javascript'>
var viewModel = {
name: ko.observable('Bert'),
age: ko.observable(78),
makeOlder: function () {
this.age(this.age() +1);
}
};
ko.applyBindings(viewModel);
</script>

当引用的observable(dependent observable)数据改变的时候,Knockout会自动从新render模板。在这个例子里,每次点击button的时候都会从新render模板。java

 

语法node

你可使用任何你模板引擎支持的语法。jquery.tmpl执行以下语法:jquery

 

和observable数组一块儿使用{{each}}编程

固然使用{{each someArray}}的时候,若是你的值是observableArray,你必须使用JavaScript类型的基础数组类型{{each myObservableArray()}},而不是{{each myObservableArray}}。api

 

参数数组

    主参数缓存

        语法快速记忆:若是你声明的仅仅是字符串(上个例子),KO会使用模板的ID来render。应用在模板上的数据是你的整个view model对象(例如ko.applyBindings 绑定的对象)。

        更多控件,你能够传带有以下属性的JavaScript对象:

            name(必选项) — 须要render的模板ID – 参考 注5 如何使用function函数声明ID。

            data(可选项) — 须要render到模板的数据。若是你忽略整个参数,KO将查找foreach参数,或者是应用整个view model对象。

            foreach(可选项) — 指定KO按照“foreach”模式render模板 – 参考 注3。

            afterAdd或beforeRemove(可选项) — 在foreach模式下使用callback函数。

            templateOptions(可选项) — 在render模板的时候,传递额外数据以便使用。参考 注6。

 

传递多个参数的例子:

<div data-bind='template: { name: "personTemplate", data: someObject }'> </div>

 

注1:Render嵌套模板

由于在模板里使用的是data-bind属性来声明的,因此嵌套模板你能够再次使用data-bind='template: ...',在上层模板的元素里。

这比模板引发的原生语法好用多了(例如jquery.tmpl里的{{tmpl}})。Knockout语法的好处在于能够在每层模板的跟着相关的依赖值,因此若是依赖改变了,KO将只会从新render依赖所在的那个模板。这将很大地改善了性能。

 

注2:${ val }和<span data-bind='text: val'></span>有何不一样?

当你在模板内部使用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 }语法比较简洁,若是你的模板比较小的话,仍是更合适的,不会带来大的性能问题。

 

注3:使用foreach

若是须要为集合里的每个item render一次模板,有2种方式:

    你可使用模板引擎里的原生“each”语法,对jquery.tmpl来讲就是用{{each}}语法迭代数组。

    另一种方式就是用Knockout的foreach模式来render。

 

例子:

<div data-bind='template: { name: "personTemplate",
foreach: someObservableArrayOfPeople }'> </div>

 

foreach模板模式的好处是:

  • 当往你的collection集合里添加新item项的时候,KO只会对这个新item进行render模板,而且将结果附加到现有的DOM上。
  • 当从collection集合里删除item的时候,KO将不会从新render任何模板,而只是简单地删除相关的元素。
  • KO容许经过自定义的方式声明afterAdd和beforeRemove的callback函数添加/删除DOM元素。而后这个callback会在删除元素的时候进行一些动画或者其它操做。

与原生的each不一样之处是:在改变以后,模板引擎强制从新render模板里全部的内容,由于它根本就不关注KO里所谓的依赖跟踪内容。

关于使用foreach模式的例子,参考grid editor和animated transitions。

 

注4:使用afterRender选项

有时候,你须要在模板生成的DOM元素上深度定义逻辑。例如,你可能想再模板输出的时候进行截获,而后在render的元素上容许jQuery UI命令(好比date picker,slider,或其它)。

你可使用afterRender选项,简单声明一个function函数(匿名函数或者view model里的函数),在render或者从新render模板以后Knockout会从新调用它。若是你使用的是foreach,那在每一个item添加到observable数组以后, Knockout会当即调用afterRender的callback函数。例如,

<div data-bind='template: { name: "personTemplate",
data: myData,
afterRender: myPostProcessingLogic }'> </div>

… 在view model里声明一个相似的函数(例如,对象包含myData):

viewModel.myPostProcessingLogic = function (elements) {
// "elements" is an array of DOM nodes just rendered by the template
// You can add custom post-processing logic here
}

 

注5:动态决定使用哪一个模板

有时候,你可能须要根据数据的状态来决定使用哪一个模板的ID。能够经过function的返回ID应用到name选择上。若是你用的是foreach模板模式, Knockout会对每一个item执行function(将item做为参数)从而将返回值做为ID,不然,该function接受的参数是整个 data option或者是整个view model。

 

例子:

<ul data-bind='template: { name: displayMode,
foreach: employees }'> </ul>
<script type='text/javascript'>
var viewModel = {
employees: ko.observableArray([
{ name: "Kari", active: ko.observable(true) },
{ name: "Brynn", active: ko.observable(false) },
{ name: "Nora", active: ko.observable(false) }
]),
displayMode: function (employee) {
return employee.active() ?"active" : "inactive";
// Initially "Kari" uses the "active" template, while the others use "inactive"
}
};

// ... then later ...
viewModel.employees()[1].active(true);
// Now "Brynn" is also rendered using the "active" template.
</script>

若是你的function引用的是observable值,那当这些值改变的时候,绑定的值会随着改变的。这将致使相应的模板从新render。

 

注6:使用templateOptions传递额外的参数

若是你在绑定模板的时候须要传入额外的数据的话,你可使用templateOptions对象来传递这些值。这能够帮助你经过一些 不属于view model过滤条件或者字符来重用模板。另一个好处是用在范围控制,你能够引用经过你的模板访问怒道的数据。

 

例子,

<ul data-bind='template: { name: "personTemplate",
foreach: employees,
templateOptions: { label: "Employee:",
selectedPerson: selectedEmployee } }'> </ul>


<script id='personTemplate' type='text/html'>
<div data-bind="css: { selected: $data === $item.selectedPerson()" }">
${ $item.label } <input data-bind="value: name" />
</div>
</script>

在整个例子里,personTemplate有可能都使用employee和自定义对象。经过templateOptions咱们能够传递一个字符label和当前已选择项做为selectedPerson来控制style。在jquery.tmpl模板里,这些值能够经过访问$item对象的属性获得。

 

注7:模板是被预编译和缓存的

为了最大性能,Knockout内嵌模板引擎jquery.tmpl会利用自身的功能对你的模板进行预编译成可执行的JavaScript代码,而后从编译流程里缓存输出。这将使模板更快更加具备可执行性,尤为是是使用foreach循环来render相同模板的时候。

通常状况你不会注意到这个,因此常常会忘记。不过,当你在某种缘由下经过编程重写模板<script>元素的时候而且该模板以前已经用过一次的话,你的改变不会带来任何render的变化,由于在第一次使用的时候已经预编译了而且缓存起来了。(若是这些会带来问题,咱们将考虑在KO新版本里提供一个禁用或重设模板缓存的功能,不过好像没有好的缘由去动态改变模板<script>元素的内容)。

 

注8:使用不一样的模板引擎

若是你想使用不一样的JavaScript模板引擎(或者是由于某些缘由你不想在jQuery上使用依赖)。咱们能够去为KO来写一个不一样的模板引擎,例如,在KO源代码里的jqueryTmplTemplateEngine.js,尽管他是为了支持多个版本的jquery.tmpl而编译。支持一个单独的模板引擎版本相对简单多了。

 

依赖性

template绑定只能在引用合适的模板引擎状况下才能工做。例如提到的jquery.tmpl引擎。

 

点击查看本系列教程目录

相关文章
相关标签/搜索