KnockoutJs学习笔记(五)

时间:2022-05-10 09:16:19

作为一名初学者来说,一篇篇的按顺序看官网上的文档的确是一件很痛苦的事情,毕竟它的排列也并非是由浅及深的排列,其中的顺序也颇耐人寻味,于是这篇文章我又跳过了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,实际上页面显示出来的是:

KnockoutJs学习笔记(五)

可以看出我们添加的p元素并没有显示出来,接下来我在js部分修改了shouldShowMessage的值:

 myViewModel.shouldShowMessage(true);

页面变成了这样:

KnockoutJs学习笔记(五)

此时的页面中显示出了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>

页面显示效果如下:

KnockoutJs学习笔记(五)

利用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>

页面效果如下:

KnockoutJs学习笔记(五)

在上例中的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>");

显示出来会是:

KnockoutJs学习笔记(五)

这样也可以防止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>

页面的效果如下:

KnockoutJs学习笔记(五)

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;
}

页面显示效果如下:

KnockoutJs学习笔记(五)

另外,我们也可以通过绑定一个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;
}

页面显示效果如下:

KnockoutJs学习笔记(五)

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;
}

页面显示效果如下:

KnockoutJs学习笔记(五)

在上例中,我们是使用两个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>

页面显示效果如下:

KnockoutJs学习笔记(五)

对于某些带有特殊符号的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>

页面显示效果如下:

KnockoutJs学习笔记(五)

与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}" />

页面显示效果如下:

KnockoutJs学习笔记(五)

如果绑定的viewModelProperty是一个observable,则每次observable改变时,UI均会更新相应的attribute;否则,UI只会设定一次attribute,之后不再更新。

当attribute name中带有连字符号时,我们只需在其外部添加一对引号即可。

KnockoutJs学习笔记(五)的更多相关文章

  1. C&num;可扩展编程之MEF学习笔记&lpar;五&rpar;:MEF高级进阶

    好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用 ...

  2. (转)Qt Model&sol;View 学习笔记 &lpar;五&rpar;——View 类

    Qt Model/View 学习笔记 (五) View 类 概念 在model/view架构中,view从model中获得数据项然后显示给用户.数据显示的方式不必与model提供的表示方式相同,可以与 ...

  3. java之jvm学习笔记五&lpar;实践写自己的类装载器&rpar;

    java之jvm学习笔记五(实践写自己的类装载器) 课程源码:http://download.csdn.net/detail/yfqnihao/4866501 前面第三和第四节我们一直在强调一句话,类 ...

  4. Learning ROS for Robotics Programming Second Edition学习笔记&lpar;五&rpar; indigo computer vision

    中文译著已经出版,详情请参考:http://blog.csdn.net/ZhangRelay/article/category/6506865 Learning ROS for Robotics Pr ...

  5. Typescript 学习笔记五:类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. ES6学习笔记&lt&semi;五&gt&semi; Module的操作——import、export、as

    import export 这两个家伙对应的就是es6自己的 module功能. 我们之前写的Javascript一直都没有模块化的体系,无法将一个庞大的js工程拆分成一个个功能相对独立但相互依赖的小 ...

  7. muduo网络库学习笔记&lpar;五&rpar; 链接器Connector与监听器Acceptor

    目录 muduo网络库学习笔记(五) 链接器Connector与监听器Acceptor Connector 系统函数connect 处理非阻塞connect的步骤: Connetor时序图 Accep ...

  8. python3&period;4学习笔记&lpar;五&rpar; IDLE显示行号问题,插件安装和其他开发工具介绍

    python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...

  9. Go语言学习笔记五: 条件语句

    Go语言学习笔记五: 条件语句 if语句 if 布尔表达式 { /* 在布尔表达式为 true 时执行 */ } 竟然没有括号,和python很像.但是有大括号,与python又不一样. 例子: pa ...

  10. 【opencv学习笔记五】一个简单程序:图像读取与显示

    今天我们来学习一个最简单的程序,即从文件读取图像并且创建窗口显示该图像. 目录 [imread]图像读取 [namedWindow]创建window窗口 [imshow]图像显示 [imwrite]图 ...

随机推荐

  1. 多线程 异步 beginInvoke EndInvoke 使用

    有许多耗时操作时,还要响应用户操作.这时候就需要用其他线程或者异步来搞.本来是改造公司的日志组件.因为多上了个国外大区的业务到来本系统来.这个系统其他地方都好就是日志,动不动就要死给我们看.有时候寻找 ...

  2. React Native 的ES5 ES6写法对照表

    模块 引用 在ES5里,如果使用CommonJS标准,引入React包基本通过require进行,代码类似这样: //ES5 var React = require("react" ...

  3. Excel jxl导入导出

    JAVA EXCEL API简介 Java Excel是一开放源码项目,通过它Java开发人员可以读取Excel文件的内容.创建新的Excel文件.更新已经存在的Excel文件.使用该API非Wind ...

  4. codeforces 468A&period; 24 Game 解题报告

    题目链接:http://codeforces.com/problemset/problem/468/A 题目意思:给出一个数n,利用 1 - n 这 n 个数,每个数只能用一次,能否通过3种运算: + ...

  5. launch文件概述---1

    摘要: 原创博客:转载请表明出处:http://www.cnblogs.com/zxouxuewei/ 资源链接:http://wenku.baidu.com/link?url=PhyN3C6ghqo ...

  6. 破解Windows Server 2003只允许3个用户远程登陆

    导读:WIN2003在使用远程桌面登录的时候,一台机器默认情况下只允许3个用户同时登录. 这很不方便.我们修改WIN2003远程桌面的连接数,可以设置3个以上用户远程桌面. 1.启动终端服务:在&qu ...

  7. linux中的一些基础命令的使用&lpar;which&comma;whereis&comma;locate&comma;find&comma;alias&comma;file&comma;ls&comma;cat&comma;echo&comma;tar&comma;bzip2&comma;gzip&comma;history&comma;mv&comma;cp&comma;rm&rpar;

    which whereis locate find alias file ls cat echotar bzip2 gzip history mv cp rm -------------------- ...

  8. js原生实现抽奖活动(方形非圆盘)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. Xamarin Essentials教程屏幕常亮ScreenLock

    Xamarin Essentials教程屏幕常亮ScreenLock   在一段时间内,如果用户没有对设备进行操作,设备就会自动关闭屏幕.用户必须手动操作,才能点亮屏幕.但是很多应用需要在用户没有操作 ...

  10. ZOJ 2110 C - Tempter of the Bone

    https://vjudge.net/contest/67836#problem/C The doggie found a bone in an ancient maze, which fascina ...