template的作用是用模板来填充相关的DOM元素。它提供了一种简单的方法来用视图模型的方法构建复杂的UI结构。
template有两种使用方式:
foreach
、if
、with
等流程控制的绑定。这些绑定捕捉元素内的html片段,将其作为模板。template参数为字符传值时,ko会把它当成模板的ID。提供给模板的数据就是当前的上下文模型对象。
template参数为js对象时,可以有以下属性:
afterRender
、afterAdd
、beforeRemove
:渲染DOM元素后的回调函数。例1:渲染一个具名模板
使用流程控制绑定时,可以将模板隐式并匿名地定义在DOM元素的内部,这时模板就不需要name。也可以将模板提出来,放到单独的DOM元素中,并为其指定name。
<h2>Participants</h2>
Here are the participants:
<div data-bind="template: { name: 'person-template', data: buyer }"></div>
<div data-bind="template: { name: 'person-template', data: seller }"></div>
<script type="text/html" id="person-template">
<h3 data-bind="text: name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</script>
<script type="text/javascript">
function MyViewModel() {
this.buyer = { name: 'Franklin', credits: 250 };
this.seller = { name: 'Mario', credits: 5800 };
}
ko.applyBindings(new MyViewModel());
</script>
例2:具名模板使用foreach选项
<h2>Participants</h2>
Here are the participants:
<div data-bind="template: { name: 'person-template', foreach: people }"></div>
<script type="text/html" id="person-template">
<h3 data-bind="text: name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</script>
function MyViewModel() {
this.people = [
{ name: 'Franklin', credits: 250 },
{ name: 'Mario', credits: 5800 }
]
}
ko.applyBindings(new MyViewModel());
上面的视图与下面的是等价的:
<div data-bind="foreach: people">
<h3 data-bind="text: name"></h3>
<p>Credits: <span data-bind="text: credits"></span></p>
</div>
例3:使用as为foreach项赋别名
在嵌套的foreach模板中,可以使用$parent
等绑定上下文来访问更高层的对象。更简单且优雅的方式是使用as。
<ul data-bind="template: { name: 'seasonTemplate', foreach: seasons, as: 'season' }"></ul>
<script type="text/html" id="seasonTemplate">
<li>
<strong data-bind="text: name"></strong>
<ul data-bind="template: { name: 'monthTemplate', foreach: months, as: 'month' }"></ul>
</li>
</script>
<script type="text/html" id="monthTemplate">
<li>
<span data-bind="text: month"></span>
is in
<span data-bind="text: season.name"></span>
</li>
</script>
<script>
var viewModel = {
seasons: ko.observableArray([
{ name: 'Spring', months: [ 'March', 'April', 'May' ] },
{ name: 'Summer', months: [ 'June', 'July', 'August' ] },
{ name: 'Autumn', months: [ 'September', 'October', 'November' ] },
{ name: 'Winter', months: [ 'December', 'January', 'February' ] }
])
};
ko.applyBindings(viewModel);
</script>
注意,传递给as的是一个字符串字面量而不是变量,因为这里是为一个新变量命名,而不是读取一个已存在的变量的值。
例4:动态选择模板
如果有多个具名模板,可以为name
传递一个监控变量,当监控变量的值发生变化时,元素的内容会使用相应的模板重新渲染。也可以传递一个回调函数来决定使用哪个模板。如果时foreach模板模式,ko会对数组的每一项进行处理,将数组项的值作为唯一参数。否则,参数会是data
的值,或回退到整个当前模型对象。函数的第二个参数是绑定上下文,因此在动态选择模板时可以使用$parent
等绑定上下文。
如果函数中引用了监控变量,那么变量变化时,绑定也会更新,也就是说,会根据数据和相应的模板重新渲染。
<ul data-bind='template: { name: displayMode,
foreach: employees }'> </ul>
<script>
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) {
// Initially "Kari" uses the "active" template, while the others use "inactive"
return employee.active() ? "active" : "inactive";
}
};
// ... then later ...
viewModel.employees()[1].active(true); // Now "Brynn" is also rendered using the "active" template.
</script>
例5:使用基于字符串的外部模板引擎jQuery.tmpl
使用jQuery.tmpl时,需要引用jQuery和jQuery.tmpl。目前jQuery.tmpl已停止更新,不建议使用。
<h1>People</h1>
<div data-bind="template: 'peopleList'"></div>
<script type="text/html" id="peopleList">
{{each people}}
<p>
<b>${name}</b> is ${age} years old
</p>
{{/each}}
</script>
<script type="text/javascript">
var viewModel = {
people: ko.observableArray([
{ name: 'Rod', age: 123 },
{ name: 'Jane', age: 125 },
])
}
ko.applyBindings(viewModel);
</script>
例6:使用模板引擎Underscore
Undercore默认使用“ERB-style delimiters”(<%= ... %>
),也可以设置使用其他分割符。
<script type="text/html" id="peopleList">
<% _.each(people(), function(person) { %>
<li>
<b><%= person.name %></b> is <%= person.age %> years old
</li>
<% }) %>
</script>
参考资料:
KnockoutJS Documentation