KnockoutJs学习笔记(五)
作为一名初学者来说,一篇篇的按顺序看官网上的文档的确是一件很痛苦的事情,毕竟它的排列也并非是由浅及深的排列,其中的顺序也颇耐人寻味,于是这篇文章我又跳过了Reference部分,进而进入到具体的bindings环节,首先接触到的是Controlling text and appearance。
Visible binding会依据绑定的数据来决定相应的DOM元素是否隐藏。
我们首先在js文件部分定义一个view model,这里我创建的是一个object而不是一个构造函数,个人分析认为,object类型的定义就是一种persistent view model,而构造函数类型的定义就是一种temporary view model,这个也许和pure computed observables中的性能有关,可和knockout学习笔记(四)联系起来。
相应的js部分如下:
var myViewModel = {
shouldShowMessage: ko.observable()
}
ko.applyBindings(myViewModel);
在html部分的测试元素如下:
<p data-bind="visible: shouldShowMessage">Test for visible binding</p>
在这种情况下,由于我没有给shouldShowMessage赋一个初始值,所以应该是undefined,即对应的false,实际上页面显示出来的是:

可以看出我们添加的p元素并没有显示出来,接下来我在js部分修改了shouldShowMessage的值:
myViewModel.shouldShowMessage(true);
页面变成了这样:

此时的页面中显示出了p元素。
有关visible binding的参数:当参数是false或相当于false的值时,binding会将yourElement.style.display设置为none使得订阅的元素隐藏,而这个设定也会覆盖掉所有你自己定义的CSS样式,我猜测这是和CSS样式覆盖规则有关,knockoutjs也许就是将这一个赋值的优先级设置为最高或者是合理利用了相应的顺序,这个可以以后研究knockoutjs的源码的时候查一查。当参数是true或是相当于true的值时,binding会删去相应的yourElement.style.display,从而让用户自定义的CSS样式作用于订阅的元素上。
当参数是一个observable时,每当参数变化,UI部分的元素都会更新自己的visible属性,而当参数不是observable时,UI部分的元素只会对visible属性设定一次。当然,参数也可以是一个函数,binding会根据function返回的值是true还是false来决定是否显示相应的DOW element。
Text binding会使得相应的DOM element的text部分变为参数的值。
js部分的代码如下:
var myViewModel = {
myText: ko.observable()
}
ko.applyBindings(myViewModel);
myViewModel.myText("Hello world!");
html部分的代码如下:
<p>This is my text: <span data-bind="text: myText"></span></p>
页面显示效果如下:

利用text binding的时候,element所订阅的view model的值会覆盖掉html中现有的text部分,如果参数是一个observable,每当参数变化的时候,UI都会更新自己的text部分,而如果参数不是observable,UI只会在最初的时候设定好text,以后不再更新。如果参数不是数字类型也不是字符串类型,则binding会调用yourParameter.toString()来将其转换为text再替换掉text部分的内容。
注意一:如果我们希望通过函数来计算或者说控制输出到text部分的值,我们可以将其绑定至一个computed observable,js部分如下:
var myViewModel = {
myText: ko.observable(),
myComputed: ko.pureComputed(function() {
return myViewModel.myText() > 50 ? "Big" : "Small";
})
}
ko.applyBindings(myViewModel);
myViewModel.myText(60);
html部分如下:
<p>This is my text: <span data-bind="text: myComputed"></span></p>
页面效果如下:

在上例中的view model是作为object直接声明的,这是为了能够方便地更改其中的属性(myText)。如果将上例中的myViewModel.myText替换为this.myText,必然会报错,因为之前的文章已经提到过,function并不能算作是object的一部分,不过computed提供了一个指定this的值的方式,如果修改成以下模样:
var myViewModel = {
myText: ko.observable(),
myComputed: ko.pureComputed(function() {
return this.myText() > 50 ? "Big" : "Small";
}, this)
}
结果依然会报错:undefined is not a function。这里也许需要理清的就是函数中的this和object中的this的问题,留作以后研究。之后我换了一种方式,换成了构造函数:
function MyViewModel(myText) {
this.myText = ko.observable(myText);
this.myComputed = ko.pureComputed(function() {
return this.myText() > 50 ? "Big" : "Small";
}, this);
}
这样是可行的,我就猜想会不会是之前的例子里没有给属性添加this,经测试,object里面完全不支持this,这也是自己对javascript的理解不清晰所致,于是可以认为,在object的定义形式中,computed内所关联的observable需带上这个view model的全名,而在function的定义形式中,则可以使用this来指代当前的实例。这里又涉及到这两种定义方式的区别问题,留作以后研究。
当然,我们也可以直接将computed部分最后返回的结果用data-bind来绑定,如下:
<p>This is my text: <span data-bind="text: myText > 50 ? 'Big' : 'Small'"></span></p>
这样我们就不需要再定义一个computed observable。
注意二:如果我们传入text的参数中含有html的标签,页面中并不会将其以标签的形式展现,而是会以字符串的方式展现出来,例如:
myViewModel.myText("<i>Hello world!</i>");
显示出来会是:

这样也可以防止HTML或是script的注入攻击。而有关html标签的绑定则需要参考html binding。
注意三:在某些时候,我们需要在不指定元素的情况下直接插入text,此时我们可以使用无容器的语法来定义一个text binding。例如在option element中是不允许包含其他元素的,如果我们如下定义data-bind
<select>
<option>Item <span data-bind="text: myText"></span></option>
</select>
我们并不能得到view model中的observable,无容器的语法则是这样写的:
<select>
<option>Item <!--ko text: myText--><!--/ko--></option>
</select>
<!--ko-->和<!--/ko-->扮演着开始标志和结束标志,它们定义了一个虚拟元素,knockout语法能够理解这种写法并像对待一个最真实元素那样去绑定相应的view model内的值。
Html binding其实与text binding类似,只不过它的参数一般是带有html标签的,这样就可以自定义想要绑定的html元素。
下面是个很简单的例子:
var myViewModel = {
myHtml: ko.observable(),
}
ko.applyBindings(myViewModel);
myViewModel.myHtml("<a href='http://www.google.com'>Google</a>");
html部分如下:
<p>My html element is: <span data-bind="html: myHtml"></span></p>
页面的效果如下:

html binding的其他特性与text binding类似,但是使用html binding的时候要特别注意安全问题,防止注入式攻击等。
CSS binding主要用于根据view model的修改来更改UI中相应元素的class,从而依照CSS文件中已经定义好的样式来体现在页面中。一个简单的static css binding例子如下:
js部分:
var myViewModel = {
myTest : ko.observable(),
}
ko.applyBindings(myViewModel);
myViewModel.myTest(20);
html部分:
<p data-bind="css: { redText: myTest() > 0 }">Test for css binding</p>
css部分:
.redText {
color: red;
}
页面显示效果如下:

另外,我们也可以通过绑定一个computed observable来动态指定css class的值,这样的绑定称为dynamic css binding,简单的例子如下:
js部分:
var myViewModel1 = {
myTest: ko.observable(),
myComputed: ko.pureComputed(function() {
return myViewModel1.myTest() > 0 ? "redText" : "blueText";
})
};
var myViewModel2 = {
myTest: ko.observable(),
myComputed: ko.pureComputed(function() {
return myViewModel2.myTest() > 0 ? "redText" : "blueText";
})
};
ko.applyBindings(myViewModel1, document.getElementById("redText"));
ko.applyBindings(myViewModel2, document.getElementById("blueText"));
myViewModel1.myTest(20);
myViewModel2.myTest(-20);
html部分:
<p id="redText" data-bind="css: myComputed">This is red text.</p>
<p id="blueText" data-bind="css: myComputed">This is blue text.</p>
css部分:
.redText {
color: red;
}
.blueText {
color: blue;
}
页面显示效果如下:

css bidning是十分灵活的,对于static css binding,我们一般是以data-bind="css: {cssClass: viewModelProperty}"的形式来绑定css class,cssClass会根据viewModelProperty返回的值是true还是false来决定这个class现在是否需要使用。另外,我们也可以一次性设置多个css classes,简单的示例如下:
js部分:
var myViewModel = {
redTextDecision: ko.observable(),
textDecorationDecision: ko.observable()
};
ko.applyBindings(myViewModel);
myViewModel.redTextDecision(true);
myViewModel.textDecorationDecision(true);
html部分:
<p data-bind="css: {redText: redTextDecision, textDecoration: textDecorationDecision}">This is red text, and its text-decoration is underline.</p>
css部分:
.redText {
color: red;
}
.textDecoration {
text-decoration: underline;
}
页面显示效果如下:

在上例中,我们是使用两个view model的property来决定两个不同的css class,KO也允许我们使用一个view model property来决定多个css class,可将上例的html部分改成如下形式:
<p data-bind="css: {'redText textDecoration': redTextDecision}">This is red text, and its text-decoration is underline.</p>
这里为了简便,并没有更改相应的view model property的名称,可以看到,当对多个css class进行设定的时候,我们需要将它们统一包含在引号中。
如果绑定的view model property属性是一个observable,则UI会根据该observable的变化来动态的增加或删去被绑定的css class,否则,UI只会在开始阶段设定一次css class,之后不再更新。
dynamic css binding的一般形式是这样的:data-bind="css: viewModelProperty",UI会根据viewModelProperty返回的字符串(property本身可以是一个代表css class的字符串)来决定添加的css class的名称。如果property是一个observable,则在该observable改变的时候,UI会删去之前该observable所添加的class并重新设置为当前observable的值。在dynamic css binding中,我们可以让viewModelProperty添加多个css class,只需将这些css class以空格分开并统一以字符串的方式返回即可。一个简单的例子如下:
js部分:
var myViewModel = {
textDecorationDecision: ko.observable("textDecoration redText")
};
ko.applyBindings(myViewModel);
html部分:
<p data-bind="css: textDecorationDecision">This is red text, and its text-decoration is underline.</p>
页面显示效果如下:

对于某些带有特殊符号的css class,比如red-text,我们不能直接在data-bind中以data-bind="css: {red-text: redTextDecision}"的方式来设定,而是应该在这类css class外添加一对引号使其成为字符串常量,变成这样:data-bind="css: {'red-text': redTextDecision}"。
style binding是与css binding不同的控制页面样式的方式,css binding需要依赖css文件中对应的样式表,借由增加或删除css class来改变样式,而style binding则是直接在相应的元素上添加或删除style来改变页面的样式。一个简单的例子如下:
js部分:
var myViewModel = {
redTextDecision: ko.observable("red")
};
ko.applyBindings(myViewModel);
html部分:
<p data-bind="style: {color: redTextDecision}">This is red text.</p>
页面显示效果如下:

与css binding类似,我们也可以一次性设定多个style,如下:
<p data-bind="style: {color: redTextDecision, align: alignDecision}">This is red text.</p>
如果绑定的viewModelProperty是一个observable,则每次observable改变的同时,UI会对对应的style进行更新;否则,UI只会设定一次style,之后不再改变。
有些style是带有特殊符号的,比如"text-decoration",比如"font-size"。在这种情况下,直接在data-bind中填写style的原名是不妥的,我们须将其变更为"textDecoration"和"fontSize",其他类似的情形以此类推。
attr binding用于绑定某些元素的attribute,比如说a元素的title、href,img元素的src等。一个简单的例子如下:
js部分:
var myViewModel = {
url: ko.observable("http://www.google.com"),
description: ko.observable("This is google's website"),
imgUrl: ko.observable("YukiNagato.JPG")
};
ko.applyBindings(myViewModel);
html部分:
<a data-bind="attr {href: url, title: description}">Google's website</a>
<img style="weight: 100px; height: 100px" data-bind="attr {src: imgUrl}" />
页面显示效果如下:

如果绑定的viewModelProperty是一个observable,则每次observable改变时,UI均会更新相应的attribute;否则,UI只会设定一次attribute,之后不再更新。
当attribute name中带有连字符号时,我们只需在其外部添加一对引号即可。
KnockoutJs学习笔记(五)的更多相关文章
- C#可扩展编程之MEF学习笔记(五):MEF高级进阶
好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...
- (转)Qt Model/View 学习笔记 (五)——View 类
Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...
- java之jvm学习笔记五(实践写自己的类装载器)
java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...
- Learning ROS for Robotics Programming Second Edition学习笔记(五) indigo computer vision
中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...
- Typescript 学习笔记五:类
中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...
- ES6学习笔记<五> Module的操作——import、export、as
import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...
- muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor
目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...
- python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍
python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...
- Go语言学习笔记五: 条件语句
Go语言学习笔记五: 条件语句 if语句 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 竟然没有括号,和python很像.但是有大括号,与python又不一样. 例子: pa ...
- 【opencv学习笔记五】一个简单程序:图像读取与显示
今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...
随机推荐
- java中equals,hashcode和==的区别
https://www.cnblogs.com/kexianting/p/8508207.html
- Gradle的使用
⒈下载 点击此处 ⒉安装 1.解压 2.添加环境变量GRADLE_HOME 指向解压缩文件的磁盘地址 3.PATH环境变量添加%GRADLE_HOME%\bin ⒊使用阿里云仓库 repositori ...
- MySQL常用的sql操作
1.日期时间格式化 2.日期时间格式化 3.查询第11到第15条数据 ,5//落过多少,取出多少. 4.字符串转日期 select str_to_date('2016-01-02', '%Y-%m-% ...
- 欢迎使用 MWeb-Test
首先介绍一下 MWeb 是什么,MWeb 是专业的 Markdown 写作.记笔记.静态博客生成软件. 然后这里重点说明一下:MWeb 有两个模式,外部模式和文档库模式.外部模式中把本地硬盘或 Dro ...
- MySQL索引调优【转】
一.关于查询计划 其实,关于所有的关系型数据库中,在运行T-SQL语句的时候,在查询器进行编译运行的同时,都会有着自己的内部的一个优化过程,而这优化之后的产物就是:执行计划. 在SQL SERVER中 ...
- NODE_ENV不是内部或外部命令,也不是可运行的程序
NODE_ENV不是内部或外部命令,也不是可运行的程序 解决办法:安装across-env:npm install cross-env –save-dev 在运行命令加前缀:在NODE_ENV=xxx ...
- php无法连接mysql问题解决方法总结
http://www.163ns.com/zixun/post/5295.html 本文章总结了在php开发中可能会常常碰到的一些php连接不了mysql数据库的一些问题总结与解决方法分享,有 ...
- 【转】gcc命令中参数c和o混合使用的详解
gcc -c a.c 编译成目标文件a.o gcc a.c 生成执行文件a.exe gcc -o a -c a.c 编译成目标文件a gcc -o a a.c 生成执行文件a. ...
- modsign: could't get uefi db list
手头上一个工控机,装完 ubuntu 16.04后重启, 一直提示如下错误: modsign: could't get uefi db list 用过ubuntu的修复工具也没有成功. 后经过如下操 ...
- Unix的哲学
先讲两个很老的小故事. 第一个故事. 有一家日本最大的化妆品公司,收到了用户的投诉.用户抱怨买来的肥皂盒是空的.这家公司为了防止再发生这样的事故,很辛苦地发明了一台X光检查器,能够透视每一个出货的肥皂 ...