对于knockoutJS来讲,模板绑定和Mapping插件绑定是十分重要的功能,虽然模板绑定在我工作中用的及其少,但模板绑定的重要性不可忽视,在其他前端框架中,如Angular、Vue等等,模板存在的意义十分重要,Mapping插件使得我们能够脱离手工绑定,及其方便我们快速绑定达到预期效果。

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

一、模板绑定目的

  在mvc的开发中,对于常用的一些独立的Html,习惯将它变成分布视图或是视图组件,以此来方便调用以及重用,同时也达到解耦效果,同样在前端开发中,对于部分重用度很高、复杂度高的UI、嵌套UI等这些部分,我们也可以设计成模板。

  

  在knockoutJS中通过template绑定将模板绑定到预期DOM元素中,将模板所依赖的数据呈现。模板绑定对于构建嵌套结构的页面十分方便,默认情况, Knockout使用jquery.tmpl模板引擎,使用模板绑定时,需引用jquery.tmpl和jQuery框架,或者你也可以集成其它的模板引擎(需要了解Knockout 内部知识)。

  模板语法:

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

  具体了解模板语法可以查看:http://www.php.cn/js-tutorial-383558.html

二、模板绑定应用

  如果你仅仅是声明的字符串,KO将会使用它作为模板的ID去渲染。应用在模板上的数据是你当前的viewModel对象。

  1、构建一个简单模板

<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模板。在该例子里,每次点击按钮都会重新渲染该模板。

  2、构建一个性能更好点的简单模板

<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}这种方式也是可行的,浪费点性能,写起来快捷方便。

  3、嵌套模板

<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嵌套其他模板,模板的重新渲染以就近原则为主,最近的模板数据改变,只渲染最近的模板,对于所有的模板不进行重新渲染。

  4、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从集合中移除。

  5、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引擎已经满足我的需求了。

  代码地址:https://gitee.com/530521314/Partner.TreasureChest.git

2018-10-13,望技术有成后能回来看见自己的脚步

KnockoutJS-模板绑定的更多相关文章

  1. knockoutJS学习笔记06:ko数组与模板绑定

    前面已经介绍了基本的绑定和模板相关知识,接下来就看ko里的数组和模板绑定,数组和模板绑定应该是实际项目中用得比较多的,ko提供了很好的支持. 一.observaleArray 前面的监控属性都是单个对 ...

  2. 【Knockout.js 学习体验之旅】(3)模板绑定

    本文是[Knockout.js 学习体验之旅]系列文章的第3篇,所有demo均基于目前knockout.js的最新版本(3.4.0).小茄才识有限,文中若有不当之处,还望大家指出. 目录: [Knoc ...

  3. Windows Store App JavaScript 开发:模板绑定

    WinJS库模板提供了一种格式化显示多条数据的便捷方式,通过这种方式可以将模板与ListView或FlipView等控件结合使用以控制数据的显示格式.定义一个WinJS库模板的方法与定义WinJS库控 ...

  4. Knockout学习之模板绑定器

    模板绑定器 如今页面结构越来越复杂,仅仅依靠foreach已经不足以我们的使用,这个时候我们就需要模板的存在,模板的优点自然很多,首先会让页面整洁,同时修改起来也可以方面的定位,最重要的是ko可以条件 ...

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

    原文:Knockout应用开发指南 第四章:模板绑定 模板绑定The template binding 目的 template绑定通过模板将数据render到页面.模板绑定对于构建嵌套结构的页面非常方 ...

  6. KnockOut文档--模板绑定

    目的 模板绑定使用数据render模板,然后把渲染的结果填充到Dom树中.模板通过重复或嵌套块(通常为您的视图模型数据的函数)用一种简单,方便的方式来建立复杂的UI结构 . 有两种方式使用模板: Na ...

  7. knockoutjs模板实现树形结构列表

    数据结构 /*数据*/ var ko_vue_data=[ { name: "总能耗", number:"0", energyone: 14410, energ ...

  8. WPF 模板绑定父级控件内容

    WPF 模板绑定父级控件内容 <Style TargetType="Button" x:Key="btn"> <Setter Property ...

  9. Win10系列:JavaScript 模板绑定

    WinJS库模板提供了一种格式化显示多条数据的便捷方式,通过这种方式可以将模板与ListView或FlipView等控件结合使用以控制数据的显示格式.定义一个WinJS库模板的方法与定义WinJS库控 ...

  10. Xamarin XAML语言教程控件模板的模板绑定

    Xamarin XAML语言教程控件模板的模板绑定 控件模板的模板绑定 为了可以轻松更改控件模板中控件上的属性值,可以在控件模板中实现模板绑定功能.模板绑定允许控件模板中的控件将数据绑定到公共属性上. ...

随机推荐

  1. 【莫比乌斯反演】BZOJ2154 Crash的数字表格

    Description 求sigma lcm(x,y),x<=n,y<=m.n,m<=1e7. Solution lcm没有什么直接做的好方法,用lcm=x*y/gcd转成gcd来做 ...

  2. Spring事务(一) Markdown 版

    事务 事务的特性(ACID) 原子性(Atomicity) 原子性要求事务所包含的全部操作是一个不可分割的整体,这些操作要么全部提交成功,要么只要其中一个操作失败,就全部"成仁" ...

  3. 【爆料】-《维多利亚大学毕业证书》Victoria一模一样原件

    ☞维多利亚大学毕业证书[微/Q:865121257◆WeChat:CC6669834]UC毕业证书/联系人Alice[查看点击百度快照查看][留信网学历认证&博士&硕士&海归& ...

  4. 如何解析C语言的声明

    一个声明:int *p[] 分为四部分: (1)p (2)p右面的符号(可以什么都没有) (3)p左面的符号(可以什么都没有) (4)最左面的类型说明符 解读一个声明先从p开始,然后的顺序是:右左右左 ...

  5. Discuz3.4-SSRF-从触发点到构造payload

    目录 SSRF逆向分析 0x00 前言 0x01 收集情报 0x02 尝试逆向找到触发点 0x03 尝试构造payload 0x04 总结 SSRF逆向分析 0x00 前言 之前有复现过一些漏洞,但是 ...

  6. “崩溃了?不可能,我全 Catch 住了” | Java 异常处理

    前言 今天我们来讨论一下,程序中的错误处理. 在任何一个稳定的程序中,都会有大量的代码在处理错误,有一些业务错误,我们可以通过主动检查判断来规避,可对于一些不能主动判断的错误,例如 RuntimeEx ...

  7. Python的垃圾回收机制(引用计数+标记清除+分代回收)

    一.写在前面: 我们都知道Python一种面向对象的脚本语言,对象是Python中非常重要的一个概念.在Python中数字是对象,字符串是对象,任何事物都是对象,而它们的核心就是一个结构体--PyOb ...

  8. 工厂模式讲解, 引入Spring IOC

    目录 引入 简单工厂 抽象工厂 Spring的bean工厂 模拟Spring工厂实现 模拟IOC 引入 假设有一个司机, 需要到某个城市, 于是我们给他一辆汽车 public class Demo { ...

  9. 六大设计原则(一)SRP单一职责原则

    单一职责原则SRP(Single reponsibility principle) BO(Business Object):业务对象 Biz(Business Logic):业务逻辑 SRP最简单的例 ...

  10. CODING 研发管理系统上线全球加速,助力企业跨区域协作

    CODING 研发管理系统现已全面支持全类型代码仓库的 全球加速访问. 随着国内互联网红利的日趋枯竭与全球互联网的加速普及.越来越多的企业开始走出国门,将目光投向全世界,搭建跨国体系.跨出国门的中国企 ...