Knockout应用开发指南之绑定语法

开发 前端
Knockout使用js代码达到双向绑定的目的,类似Silverlight/WPF里的绑定一样,我们主要就是利用相关的特性进行开发的,极大地减少了代码开发量。本节主要讲Knockout的绑定语法。

第三章所有代码都需要启用KO的ko.applyBindings(viewModel);功能,才能使代码生效,为了节约篇幅,所有例子均省略了此行代码。

1 visible 绑定

目的

visible绑定到DOM元素上,使得该元素的hidden或visible状态取决于绑定的值。

例子

  1. <div data-bind="visible: shouldShowMessage"> 
  2.     You will see this message only when "shouldShowMessage" holds a true value.  
  3. </div> 
  4.  
  5. <script type="text/javascript"> 
  6.     var viewModel = {  
  7.         shouldShowMessage: ko.observable(true) // Message initially visible  
  8.     };  
  9.     viewModel.shouldShowMessage(false); // ... now it's hidden  
  10.     viewModel.shouldShowMessage(true); // ... now it's visible again  
  11. </script> 

参数

主参数

当参数设置为一个假值时(例如:布尔值false, 数字值0, 或者null, 或者undefined) ,该绑定将设置该元素的style.display值为none,让元素隐藏。它的优先级高于你在CSS里定义的任何display样式。

当参数设置为一个真值时(例如:布尔值true,或者非空non-null的对象或者数组) ,该绑定会删除该元素的style.display值,让元素可见。然后你在CSS里自定义的display样式将会自动生效。

如果参数是监控属性observable的,那元素的visible状态将根据参数值的变化而变化,如果不是,那元素的visible状态将只设置一次并且以后不在更新。

其它参数

注:使用函数或者表达式来控制元素的可见性

你也可以使用JavaScript函数或者表达式作为参数。这样的话,函数或者表达式的结果将决定是否显示/隐藏这个元素。例如:

  1. <div data-bind="visible: myValues().length > 0"> 
  2.     You will see this message only when 'myValues' has at least one member.  
  3. </div> 
  4.  
  5. <script type="text/javascript"> 
  6.     var viewModel = {  
  7.         myValues: ko.observableArray([]) // Initially empty, so message hidden  
  8.     };  
  9.     viewModel.myValues.push("some value"); // Now visible  
  10. </script> 

依赖性

除KO核心类库外,无依赖。

2 text 绑定

目的

text 绑定到DOM元素上,使得该元素显示的文本值为你绑定的参数。该绑定在显示或者上非常有用,但是你可以用在任何元素上。

例子

  1. Today's message is: <span data-bind="text: myMessage"></span>   
  2.  
  3. <script type="text/javascript"> 
  4.     var viewModel = {  
  5.         myMessage: ko.observable() // Initially blank  
  6.     };  
  7.     viewModel.myMessage("Hello, world!"); // Text appears  
  8. </script> 

参数

主参数

KO将参数值会设置在元素的innerText (IE)或textContent(Firefox和其它相似浏览器)属性上。原来的文本将会被覆盖。

如果参数是监控属性observable的,那元素的text文本将根据参数值的变化而更新,如果不是,那元素的text文本将只设置一次并且以后不在更新。

如果你传的是不是数字或者字符串(例如一个对象或者数组),那显示的文本将是yourParameter.toString()的等价内容。

其它参数

注1:使用函数或者表达式来决定text值

如果你想让你的text更可控,那选择是创建一个依赖监控属性(dependent observable),然后在它的执行函数里编码,决定应该显示什么样的text文本。

例如:

  1. The item is <span data-bind="text: priceRating"></span> today.  
  2.  
  3.  
  4. <script type="text/javascript"> 
  5.     var viewModel = {  
  6.         price: ko.observable(24.95)  
  7.     };  
  8.  
  9.     viewModel.priceRating = ko.dependentObservable(function () {  
  10.         returnthis.price() >50?"expensive" : "affordable";  
  11.     }, viewModel);  
  12. </script> 

现在,text文本将在“expensive”和“affordable”之间替换,取决于价格怎么改变。

然而,如果有类似需求的话其实没有必要再声明一个依赖监控属性(dependent observable), 你只需要按照如下代码写JavaScript表达式就可以了:

  1. The item is <span data-bind="text: price() > 50 ? 'expensive' : 'affordable'"></span> today. 

结果是一样的,但我们不需要再声明依赖监控属性(dependent observable)。

注2:关于HTML encoding

因为该绑定是设置元素的innerText或textContent (而不是innerHTML),所以它是安全的,没有HTML或者脚本注入的风险。例如:如果你编写如下代码:

  1. viewModel.myMessage("<i>Hello, world!</i>"); 

… 它不会显示斜体字,而是原样输出标签。如果你需要显示HTML内容,请参考html绑定.

注3:关于IE 6的白空格whitespace

IE6有个奇怪的问题,如果 span里有空格的话,它将自动变成一个空的span。如果你想编写如下的代码的话,那Knockout将不起任何作用:

  1. Welcome, <span data-bind="text: userName"></span> to our web site. 

… IE6 将不会显示span中间的那个空格,你可以通过下面这样的代码避免这个问题:

  1. Welcome, <span data-bind="text: userName">&nbsp;</span> to our web site. 

IE6以后版本和其它浏览器都没有这个问题

依赖性

除KO核心类库外,无依赖。

#p#

3 html 绑定

目的

html绑定到DOM元素上,使得该元素显示的HTML值为你绑定的参数。如果在你的view model里声明HTML标记并且render的话,那非常有用。

例子

  1. <div data-bind="html: details"></div>   
  2.  
  3. <script type="text/javascript"> 
  4.     var viewModel = {  
  5.         details: ko.observable() // Initially blank  
  6.     };  
  7.  
  8.     viewModel.details("<em>For further details, view the report <a href='report.html'>here</a>.</em>");  
  9.     // HTML content appears  
  10. </script>   

参数

主参数

KO设置该参数值到元素的innerHTML属性上,元素之前的内容将被覆盖。

如果参数是监控属性observable的,那元素的内容将根据参数值的变化而更新,如果不是,那元素的内容将只设置一次并且以后不在更新。

如果你传的是不是数字或者字符串(例如一个对象或者数组),那显示的文本将是yourParameter.toString()的等价内容。

其它参数

注:关于HTML encoding

因为该绑定设置元素的innerHTML,你应该注意不要使用不安全的HTML代码,因为有可能引起脚本注入攻击。如果你不确信是否安全(比如显示用户输入的内容),那你应该使用text绑定,因为这个绑定只是设置元素的text 值innerText和textContent。

依赖性

除KO核心类库外,无依赖。

4 css 绑定

目的

css绑定是添加或删除一个或多个CSS class到DOM元素上。 非常有用,比如当数字变成负数时高亮显示。(注:如果你不想应用CSS class而是想引用style属性的话,请参考style绑定。)

例子

  1. <div data-bind="css: { profitWarning: currentProfit() < 0 }"> 
  2.    Profit Information  
  3. </div> 
  4.    
  5.  
  6. <script type="text/javascript"> 
  7.     var viewModel = {  
  8.         currentProfit: ko.observable(150000)  
  9.         // Positive value, so initially we don't apply the "profitWarning" class  
  10.     };  
  11.  
  12.     viewModel.currentProfit(-50);  
  13.     // Causes the "profitWarning" class to be applied  
  14. </script> 

效果就是当currentProfit 小于0的时候,添加profitWarning CSS class到元素上,如果大于0则删除这个CSS class。

参数

主参数

该参数是一个JavaScript对象,属性是你的CSS class名称,值是比较用的true或false,用来决定是否应该使用这个CSS class。

你可以一次设置多个CSS class。例如,如果你的view model有一个叫isServre的属性,

  1. <div data-bind="css: { profitWarning: currentProfit() < 0, majorHighlight: isSevere }"> 

非布尔值会被解析成布尔值。例如, 0和null被解析成false,21和非null对象被解析成true。

如果参数是监控属性observable的,那随着值的变化将会自动添加或者删除该元素上的CSS class。如果不是,那CSS class将会只添加或者删除一次并且以后不在更新。

你可以使用任何JavaScript表达式或函数作为参数。KO将用它的执行结果来决定是否应用或删除CSS class。

其它参数

注:应用的CSS class的名字不是合法的JavaScript变量命名

如果你想使用my-class class,你不能写成这样:

  1. <div data-bind="css: { my-class: someValue }">...</div> 

… 因为my-class不是一个合法的命名。解决方案是:在my-class两边加引号作为一个字符串使用。这是一个合法的JavaScript 对象 文字(从JSON技术规格说明来说,你任何时候都应该这样使用,虽然不是必须的)。例如,

依赖性

除KO核心类库外,无依赖。

5 style 绑定

目的

style绑定是添加或删除一个或多个DOM元素上的style值。比如当数字变成负数时高亮显示,或者根据数字显示对应宽度的Bar。(注:如果你不是应用style值而是应用CSS class的话,请参考CSS绑定。)

例子

  1. <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }"> 
  2.    Profit Information  
  3. </div> 
  4.  
  5.  
  6. <script type="text/javascript"> 
  7.     var viewModel = {  
  8.         currentProfit: ko.observable(150000) // Positive value, so initially black  
  9.     };  
  10.     viewModel.currentProfit(-50); // Causes the DIV's contents to go red  
  11. </script> 

当currentProfit 小于0的时候div的style.color是红色,大于的话是黑色。

参数

主参数

该参数是一个JavaScript对象,属性是你的style的名称,值是该style需要应用的值。

你可以一次设置多个style值。例如,如果你的view model有一个叫isServre的属性,

  1. <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black', fontWeight: isSevere() ? 'bold' : '' }">...</div> 

如果参数是监控属性observable的,那随着值的变化将会自动添加或者删除该元素上的style值。如果不是,那style值将会只应用一次并且以后不在更新。

你可以使用任何JavaScript表达式或函数作为参数。KO将用它的执行结果来决定是否应用或删除style值。

其它参数

注:应用的style的名字不是合法的JavaScript变量命名

如果你需要应用font-weight或者text-decoration,你不能直接使用,而是要使用style对应的JavaScript名称。

错误: { font-weight: someValue }; 正确: { fontWeight: someValue }

错误: { text-decoration: someValue }; 正确: { textDecoration: someValue }

参考:style名称和对应的JavaScript 名称列表。

依赖性

除KO核心类库外,无依赖。

6 attr 绑定

目的

attr 绑定提供了一种方式可以设置DOM元素的任何属性值。你可以设置img的src属性,连接的href属性。使用绑定,当模型属性改变的时候,它会自动更新。

例子

  1. <a data-bind="attr: { href: url, title: details }"> 
  2.     Report  
  3. </a> 
  4.  
  5. <script type="text/javascript"> 
  6.     var viewModel = {  
  7.         url: ko.observable("year-end.html"),  
  8.         details: ko.observable("Report including final year-end statistics")  
  9.     };  
  10. </script> 

呈现结果是该连接的href属性被设置为year-end.html, title属性被设置为Report including final year-end statistics。

参数

主参数

该参数是一个JavaScript对象,属性是你的attribute名称,值是该attribute需要应用的值。

如果参数是监控属性observable的,那随着值的变化将会自动添加或者删除该元素上的attribute值。如果不是,那attribute值将会只应用一次并且以后不在更新。

其它参数

注:应用的属性名字不是合法的JavaScript变量命名

如果你要用的属性名称是data-something的话,你不能这样写:

  1. <div data-bind="attr: { data-something: someValue }">...</div> 

… 因为data-something 不是一个合法的命名。解决方案是:在data-something两边加引号作为一个字符串使用。这是一个合法的JavaScript 对象 文字(从JSON技术规格说明来说,你任何时候都应该这样使用,虽然不是必须的)。例如,

  1. <div data-bind="attr: { ‘data-something’: someValue }">...</div> 

依赖性

除KO核心类库外,无依赖。

#p#

7 click 绑定

目的

click绑定在DOM元素上添加事件句柄以便元素被点击的时候执行定义的JavaScript 函数。大部分是用在button,input和连接a上,但是可以在任意元素上使用。

例子

  1. <div> 
  2.     You've clicked <span data-bind="text: numberOfClicks"></span> times  
  3.     <button data-bind="click: incrementClickCounter">Click me</button> 
  4. </div> 
  5.  
  6.  
  7. <script type="text/javascript"> 
  8.     var viewModel = {  
  9.         numberOfClicks: ko.observable(0),  
  10.         incrementClickCounter: function () {  
  11.             var previousCount =this.numberOfClicks();  
  12.             this.numberOfClicks(previousCount +1);  
  13.         }  
  14.     };  
  15. </script> 

每次点击按钮的时候,都会调用incrementClickCounter()函数,然后更新自动更新点击次数。

参数

主参数

Click点击事件时所执行的函数。

你可以声明任何JavaScript函数 – 不一定非要是view model里的函数。你可以声明任意对象上的任何函数,例如: someObject.someFunction

View model上的函数在用的时候有一点点特殊,就是不需要引用对象的,直接引用函数本身就行了,比如直接写incrementClickCounter 就可以了,而无需写成: viewModel.incrementClickCounter(尽管是合法的)。

其它参数

注1:传参数给你的click 句柄

最简单的办法是传一个function包装的匿名函数:

  1. <button data-bind="click: function() { viewModel.myFunction('param1', 'param2') }"> 
  2.     Click me  
  3. </button> 

这样,KO就会调用这个匿名函数,里面会执行viewModel.myFunction(),并且传进了'param1' 和'param2'参数。

注2:访问事件源对象

有些情况,你可能需要使用事件源对象,Knockout会将这个对象传递到你函数的第一个参数:

  1. <button data-bind="click: myFunction"> 
  2.     Click me  
  3. </button> 
  4.  
  5.  
  6.  <script type="text/javascript"> 
  7.      var viewModel = {  
  8.          myFunction: function (event) {  
  9.              if (event.shiftKey) {  
  10.                  //do something different when user has shift key down  
  11.              } else {  
  12.                  //do normal action  
  13.              }  
  14.          }  
  15.      };  
  16. </script> 

如果你需要的话,可以使用匿名函数的第一个参数传进去,然后在里面调用:

  1. <button data-bind="click: function(event) { viewModel.myFunction(event, 'param1', 'param2') }"> 
  2.     Click me  
  3. </button> 

这样,KO就会将事件源对象传递给你的函数并且使用了。

注3: 允许执行默认事件

默认情况下,Knockout会阻止冒泡,防止默认的事件继续执行。例如,如果你点击一个a连接,在执行完自定义事件时它不会连接到href地址。这特别有用是因为你的自定义事件主要就是操作你的view model,而不是连接到另外一个页面。

当然,如果你想让默认的事件继续执行,你可以在你click的自定义函数里返回true。

注4:控制this句柄

初学者可以忽略这小节,因为大部分都用不着,高级用户可以参考如下内容:

KO在调用你定义的函数时,会将view model传给this对象(也就是ko.applyBindings使用的view model)。主要是方便你在调用你在view model里定义的方法的时候可以很容易再调用view model里定义的其它属性。例如: this.someOtherViewModelProperty。

如果你想引用其它对象,我们有两种方式:

◆ 你可以和注1里那样使用匿名函数,因为它支持任意JavaScript 对象。

◆ 你也可以直接引用任何函数对象。你可以使用bind使callback函数设置this为任何你选择的对象。例如:

  1. <button data-bind="click: someObject.someFunction.bind(someObject)"> 
  2.     Click me  
  3. </button> 

如果你是C#或Java开发人员,你可以疑惑为什么我们还要用bind函数到一个对象想,特别是像调用someObject.someFunction。 原因是在JavaScript里,函数自己不是类的一部分,他们在单独存在的对象,有可能多个对象都引用同样的someFunction函数,所以当这个函数被调用的时候它不知道谁调用的(设置this给谁)。在你bind之前运行时是不会知道的。KO默认情况下设置this对象是view model,但你可以用bind语法重定义它。

在注1里使用匿名函数的时候没有具体的要求,因为JavaScript代码 someObject.someFunction()就意味着调用someFunction,然后设置this到 someObject对象上。

注5:防止事件冒泡

默认情况下,Knockout允许click事件继续在更高一层的事件句柄上冒泡执行。例如,如果你的元素和父元素都绑定了click事件,那当你点击该元素的时候两个事件都会触发的。如果需要,你可以通过额外的绑定clickBubble来禁止冒泡。例如:

  1. <div data-bind="click: myDivHandler"> 
  2.     <button data-bind="click: myButtonHandler, clickBubble: false"> 
  3.         Click me  
  4.     </button> 
  5. </div> 

默认情况下,myButtonHandler会先执行,然后会冒泡执行myDivHandler。但一旦你设置了clickBubble为false的时候,冒泡事件会被禁止。

依赖性

除KO核心类库外,无依赖。

#p#

8 event 绑定

目的

event绑定在DOM元素上添加指定的事件句柄以便元素被触发的时候执行定义的JavaScript 函数。大部分情况下是用在keypress,mouseover和mouseout上。

例子

  1. <div> 
  2.     <div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }"> 
  3.         Mouse over me  
  4.     </div> 
  5.     <div data-bind="visible: detailsEnabled"> 
  6.         Details  
  7.     </div> 
  8. </div> 
  9.  
  10.  
  11. <script type="text/javascript"> 
  12.     var viewModel = {  
  13.         detailsEnabled: ko.observable(false),  
  14.         enableDetails: function () {  
  15.             this.detailsEnabled(true);  
  16.         },  
  17.         disableDetails: function () {  
  18.             this.detailsEnabled(false);  
  19.         }  
  20.     };  
  21. </script> 

每次鼠标在第一个元素上移入移出的时候都会调用view model上的方法来toggle detailsEnabled的值,而第二个元素会根据detailsEnabled的值自动显示或者隐藏。

参数

主参数

你需要传入的是一个JavaScript对象,他的属性名是事件名称,值是你所需要执行的函数。

你可以声明任何JavaScript函数 – 不一定非要是view model里的函数。你可以声明任意对象上的任何函数,例如: event: { mouseover: someObject.someFunction }。

View model上的函数在用的时候有一点点特殊,就是不需要引用对象的,直接引用函数本身就行了,比如直接写event: { mouseover: enableDetails } 就可以了,而无需写成: event: { mouseover: viewModel.enableDetails } (尽管是合法的)。

其它参数

9 submit 绑定

目的

submit绑定在form表单上添加指定的事件句柄以便该form被提交的时候执行定义的JavaScript 函数。只能用在表单form元素上。

当你使用submit绑定的时候, Knockout会阻止form表单默认的submit动作。换句话说,浏览器会执行你定义的绑定函数而不会提交这个form表单到服务器上。可以很好地解释这个,使用submit绑定就是为了处理view model的自定义函数的,而不是再使用普通的HTML form表单。如果你要继续执行默认的HTML form表单操作,你可以在你的submit句柄里返回true。

例子

  1. <form data-bind="submit: doSomething"> 
  2.     ... form contents go here ...  
  3.     <button type="submit">Submit</button> 
  4. </div> 
  5.  
  6. <script type="text/javascript"> 
  7.     var viewModel = {  
  8.         doSomething: function (formElement) {  
  9.             // ... now do something  
  10.         }  
  11.     };  
  12. </script> 

这个例子里,KO将把整个form表单元素作为参数传递到你的submit绑定函数里。 你可以忽略不管,但是有些例子里是否有用,参考:ko.postJson工具。

为什么不在submit按钮上使用click绑定?

在form上,你可以使用click绑定代替submit绑定。不过submit可以handle其它的submit行为,比如在输入框里输入回车的时候可以提交表单。

参数

主参数

你绑定到submit事件上的函数

你可以声明任何JavaScript函数 – 不一定非要是view model里的函数。你可以声明任意对象上的任何函数,例如: submit: someObject.someFunction。

View model上的函数在用的时候有一点点特殊,就是不需要引用对象的,直接引用函数本身就行了,比如直接写submit: doSomething就可以了,而无需写成: submit: viewModel. doSomething(尽管是合法的)。

其它参数

备注:

关于如果传递更多的参数给submit绑定函数,或者当调用非view model里的函数的时如何控制this,请参考click绑定。所有click绑定相关的notes也都适用于submit绑定。

依赖性

除KO核心类库外,无依赖。

10 enable 绑定

目的

enable绑定使DOM元素只有在参数值为 true的时候才enabled。在form表单元素input,select,和textarea上非常有用。

例子

  1. <p> 
  2.     <input type='checkbox' data-bind="checked: hasCellphone"/> 
  3.     I have a cellphone  
  4. </p> 
  5.  
  6. <p> 
  7.     Your cellphone number:  
  8.     <input type='text' data-bind="value: cellphoneNumber, enable: hasCellphone"/> 
  9. </p> 
  10.    
  11. <script type="text/javascript"> 
  12.     var viewModel = {  
  13.         hasCellphone: ko.observable(false),  
  14.         cellphoneNumber: ""  
  15.     };  
  16. </script> 

这个例子里,“Your cellphone number”后的text box 初始情况下是禁用的,只有当用户点击标签 “I have a cellphone”的时候才可用。

参数

主参数

声明DOM元素是否可用enabled。

非布尔值会被解析成布尔值。例如0和null被解析成false,21和非null对象被解析给true。

如果你的参数是observable的,那绑定会随着observable值的改变而自动更新enabled/disabled状态。如果不是,则只会设置一次并且以后不再更新。

其它参数

注:任意使用JavaScript表达式

不紧紧限制于变量 – 你可以使用任何JavaScript表达式来控制元素是否可用。例如,

  1. <button data-bind="enabled: parseAreaCode(viewModel.cellphoneNumber()) != '555'"> 
  2.     Do something  
  3. </button> 

依赖性

除KO核心类库外,无依赖。

11 disable 绑定

目的

disable绑定使DOM元素只有在参数值为 true的时候才disabled。在form表单元素input,select,和textarea上非常有用。

disable绑定和enable绑定正好相反,详情请参考enable绑定。

#p#

12 value 绑定

目的

value绑定是关联DOM元素的值到view model的属性上。主要是用在表单控件<input>,<select>和<textarea>上。

当用户编辑表单控件的时候, view model对应的属性值会自动更新。同样,当你更新view model属性的时候,相对应的元素值在页面上也会自动更新。

注:如果你在checkbox或者radio button上使用checked绑定来读取或者写入元素的 checked状态,而不是value 值的绑定。

 

例子

  1. <p>Login name: <input data-bind="value: userName"/></p> 
  2. <p>Password: <input type="password" data-bind="value: userPassword"/></p> 
  3.    
  4.  
  5. <script type="text/javascript"> 
  6.     var viewModel = {  
  7.         userName: ko.observable(""),        // Initially blank  
  8.         userPassword: ko.observable("abc"), // Prepopulate  
  9.     };  
  10. </script> 

 

参数

主参数

KO设置此参数为元素的value值。之前的值将被覆盖。

如果参数是监控属性observable的,那元素的value值将根据参数值的变化而更新,如果不是,那元素的value值将只设置一次并且以后不在更新。

如果你提供的参数不是一个数字或者字符串(而是对象或者数组)的话,那显示的value值就是yourParameter.toString() 的内容(通常没用,所以最好都设置为数字或者字符串)。

不管什么时候,只要你更新了元素的值,那 KO都会将view model对应的属性值自动更新。默认情况下当用户离开焦点(例如onchange事件)的时候,KO才更新这个值,但是你可以通过第2个参数valueUpdate来特别指定改变值的时机。

其它参数

valueUpdate

如果你使用valueUpdate参数,那就是意味着KO将使用自定义的事件而不是默认的离开焦点事件。下面是一些最常用的选项:

“change”(默认值) - 当失去焦点的时候更新view model的值,或者是<select> 

“keyup” – 当用户敲完一个字符以后立即更新view model。

“keypress” – 当用户正在敲一个字符但没有释放键盘的时候就立即更新view model。不像 keyup,这个更新和keydown是一样的。

“afterkeydown” – 当用户开始输入字符的时候就更新view model。主要是捕获浏览器的keydown事件或异步handle事件。

上述这些选项,如果你想让你的view model进行实时更新,使用“afterkeydown”是最好的选择。

例子:

  1. <p>Your value: <input data-bind="value: someValue, valueUpdate: 'afterkeydown'"/></p> 
  2. <p>You have typed: <span data-bind="text: someValue"></span></p> <!-- updates in real-time -->   
  3.  
  4. <script type="text/javascript"> 
  5.     var viewModel = {  
  6.         someValue: ko.observable("edit me")  
  7.     };  
  8. </script> 

注1:绑定下拉菜单drop-down list(例如SELECT)

Knockout对下拉菜单drop-down list绑定有一个特殊的支持,那就是在读取和写入绑定的时候,这个值可以是任意JavaScript对象,而不必非得是字符串。在你让你用户选择一组model对象的时候非常有用。具体例子,参考options绑定。

类似,如果你想创建一个multi-select list,参考selectedOptions绑定。

注2:更新observable和non-observable属性值

如果你用value绑定将你的表单元素和你的observable属性关联起来,KO设置的2-way的双向绑定,任何一方改变都会更新另外一方的值。

但是,如果你的元素绑定的是一个non-observable属性(例如是一个原始的字符串或者JavaScript表达式) ,KO会这样执行:

◆ 如果你绑定的non-observable属性是简单对象,例如一个常见的属性值,KO会设置这个值为form表单元素的初始值,如果你改变form表单元素的值,KO会将值重新写回到view mode的这个属性。但当这个属性自己改变的时候,元素却不会再变化了(因为不是observable的),所以它仅仅是1-way绑定。

◆ 如果你绑定的non-observable属性是复杂对象,例如复杂的JavaScript 表达式或者子属性,KO也会设置这个值为form表单元素的初始值,但是改变form表单元素的值的时候,KO不会再写会view model属性,这种情况叫one-time-only value setter,不是真正的绑定。

例子:

  1. <p>First value: <input data-bind="value: firstValue"/></p>          <!-- two-way binding --> 
  2. <p>Second value: <input data-bind="value: secondValue"/></p>        <!-- one-way binding --> 
  3. <p>Third value: <input data-bind="value: secondValue.length"/></p>  <!-- no binding -->   
  4.  
  5. <script type="text/javascript"> 
  6.     var viewModel = {  
  7.         firstValue: ko.observable("hello"), // Observable  
  8.         secondValue: "hello, again"// Not observable  
  9.     };  
  10.     ko.applyBindings(viewModel);  
  11. </script> 

依赖性

除KO核心类库外,无依赖。

 

13 checked 绑定

目的

checked绑定是关联到checkable的form表单控件到view model上 - 例如checkbox(<input type='checkbox'>)或者radio button(<input type='radio'>) 。当用户check关联的form表单控件的时候,view model对应的值也会自动更新,相反,如果view model的值改变了,那控件元素的check/uncheck状态也会跟着改变。

注:对text box,drop-down list和所有non-checkable的form表单控件,用value绑定来读取和写入是该元素的值,而不是checked绑定。

例子

  1. <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p>   
  2.  
  3. <script type="text/javascript"> 
  4.     var viewModel = {  
  5.         wantsSpam: ko.observable(true) // Initially checked  
  6.     };  
  7.  
  8.      // ... then later ...  
  9.     viewModel.wantsSpam(false); // The checkbox becomes unchecked  
  10. </script> 

Checkbox关联到数组

  1. <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p> 
  2. <div data-bind="visible: wantsSpam"> 
  3.     Preferred flavors of spam:  
  4.     <div><input type="checkbox" value="cherry" data-bind="checked: spamFlavors"/> Cherry</div> 
  5.     <div><input type="checkbox" value="almond" data-bind="checked: spamFlavors"/> Almond</div> 
  6.     <div><input type="checkbox" value="msg" data-bind="checked: spamFlavors"/> Monosodium Glutamate</div> 
  7. </div> 
  8.  
  9.    
  10. <script type="text/javascript"> 
  11.  
  12.     var viewModel = {  
  13.         wantsSpam: ko.observable(true),  
  14.         spamFlavors: ko.observableArray(["cherry", "almond"]) // Initially checks the Cherry and Almond checkboxes  
  15.     };  
  16.  
  17.     // ... then later ...  
  18.     viewModel.spamFlavors.push("msg"); // Now additionally checks the Monosodium Glutamate checkbox  
  19. </script> 

添加radio button

  1. <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p> 
  2.  
  3. <div data-bind="visible: wantsSpam"> 
  4.     Preferred flavor of spam:  
  5.     <div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor"/> Cherry</div> 
  6.     <div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor"/> Almond</div> 
  7.     <div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor"/> Monosodium Glutamate</div> 
  8. </div> 
  9.  
  10.    
  11. <script type="text/javascript"> 
  12.  
  13.     var viewModel = {  
  14.         wantsSpam: ko.observable(true),  
  15.         spamFlavor: ko.observable("almond") // Initially selects only the Almond radio button  
  16.     };  
  17.  
  18.      // ... then later ...  
  19.     viewModel.spamFlavor("msg"); // Now only Monosodium Glutamate is checked  
  20. </script> 

参数

主参数

KO会设置元素的checked状态匹配到你的参数上,之前的值将被覆盖。对参数的解析取决于你元素的类型:

对于checkbox,当参数为true的时候,KO会设置元素的状态为checked,反正设置为unchecked。如果你传的参数不是布尔值,那KO将会解析成布尔值。也就是说非0值和非null对象,非空字符串将被解析成true,其它值都被解析成false。

当用户check或者uncheck这个checkbox的时候,KO会将view model的属性值相应地设置为true或者false。

一个特殊情况是参数是一个数组,如果元素的值存在于数组,KO就会将元素设置为checked,如果数组里不存在,就设置为unchecked。如果用户对checkbox进行check或uncheck,KO就会将元素的值添加数组或者从数组里删除。

对于radio buttons,KO只有当参数值等于radio button value属性值的时候才设置元素为checked状态。所以参数应是字符串。在上面的例子里只有当view model 的spamFlavor 属性等于“almond”的时候,该radio button才会设置为checked。

当用户将一个radio button选择上的时候 is selected,KO会将该元素的value属性值更新到view model属性里。上面的例子,当点击value= “cherry”的选项上, viewModel.spamFlavor的值将被设置为“cherry”。

当然,最有用的是设置一组radio button元素对应到一个单个的view model 属性。确保一次只能选择一个radio button需要将他们的name属性名都设置成一样的值(例如上个例子的flavorGroup值)。这样的话,一次就只能选择一个了。

如果参数是监控属性observable的,那元素的checked状态将根据参数值的变化而更新,如果不是,那元素的value值将只设置一次并且以后不在更新。

其它参数

 

依赖性

除KO核心类库外,无依赖。

 

14 options 绑定

目的

options绑定控制什么样的options在drop-down列表里(例如:<select>)或者 multi-select 列表里 (例如:<select size='6'>)显示。此绑定不能用于<select>之外的元素。关联的数据应是数组(或者是observable数组),<select>会遍历显示数组里的所有的项。

 

注:对于multi-select列表,设置或者获取选择的多项需要使用selectedOptions绑定。对于single-select列表,你也可以使用value绑定读取或者设置元素的selected项。

 

例1:Drop-down list

  1. <p>Destination country: <select data-bind="options: availableCountries"></select></p> 
  2.  
  3.    
  4. <script type="text/javascript"> 
  5.     var viewModel = {  
  6.         availableCountries: ko.observableArray(['France', 'Germany', 'Spain']) // These are the initial options  
  7.     };  
  8.  
  9.     // ... then later ...  
  10.     viewModel.availableCountries.push('China'); // Adds another option  
  11. </script> 

 

例2:Multi-select list

  1. <p>Choose some countries you'd like to visit: <select data-bind="options: availableCountries" size="5" multiple="true"></select></p> 
  2.    
  3. <script type="text/javascript"> 
  4.     var viewModel = {  
  5.         availableCountries: ko.observableArray(['France', 'Germany', 'Spain'])  
  6.     };  
  7. </script> 

例3:Drop-down list展示的任意JavaScript对象,不仅仅是字符串

  1. <p> 
  2.     Your country:  
  3.     <select data-bind="options: availableCountries,   
  4.               optionsText: 'countryName', value: selectedCountry, optionsCaption: 'Choose...'"></select> 
  5. </p> 
  6.  
  7. <div data-bind="visible: selectedCountry"> <!-- Appears when you select something --> 
  8.     You have chosen a country with population  
  9.     <span data-bind="text: selectedCountry() ? selectedCountry().countryPopulation : 'unknown'"></span>.  
  10. </div> 
  11.  
  12. <script type="text/javascript"> 
  13.     // Constructor for an object with two properties  
  14. var country =function (name, population) {  
  15.         this.countryName = name;  
  16.         this.countryPopulation = population;  
  17.     };  
  18.  
  19.      var viewModel = {  
  20.         availableCountries: ko.observableArray([  
  21.             new country("UK", 65000000),  
  22.             new country("USA", 320000000),  
  23.             new country("Sweden", 29000000)  
  24.         ]),  
  25.         selectedCountry: ko.observable() // Nothing selected by default  
  26.     };  
  27. </script> 

例4:Drop-down list展示的任意JavaScript对象,显示text是function的返回值

  1. <!-- Same as example 3, except the <select> box expressed as follows: --> 
  2.  
  3. <select data-bind="options: availableCountries,  
  4.                    optionsText: function(item) {  
  5.                        return item.countryName + ' (pop: ' + item.countryPopulation + ')'  
  6.                    },  
  7.                    value: selectedCountry,  
  8.                    optionsCaption: 'Choose...'"></select> 

注意例3和例4在optionsText值定义上的不同。

 

参数

主参数

该参数是一个数组(或者observable数组)。对每个item,KO都会将它作为一个<option> 添加到<select>里,之前的options都将被删除。

如果参数是一个string数组,那你不需要再声明任何其它参数。<select>元素会将每个string显示为一个option。不过,如果你让用户选择的是一个JavaScript对象数组(不仅仅是string),那就需要设置optionsText和optionsValue这两个参数了。

如果参数是监控属性observable的,那元素的options项将根据参数值的变化而更新,如果不是,那元素的value值将只设置一次并且以后不在更新。

 

其它参数

optionsCaption

有时候,默认情况下不想选择任何option项。但是single-select drop-down列表由于每次都要默认选择以项目,怎么避免这个问题呢?常用的方案是加一个“请选择的”或者“Select an item”的提示语,或者其它类似的,然后让这个项作为默认选项。

我们使用optionsCaption参数就能很容易实现,它的值是字符串型,作为默认项显示。例如:

<select data-bind='options: myOptions, optionsCaption: "Select an item...", value: myChosenValue'></select>

KO会在所有选项上加上这一个项,并且设置value值为undefined。所以,如果myChosenValue被设置为undefined(默认是observable的),那么上述的第一个项就会被选中。

 

optionsText

上面的例3展示的绑定JavaScript对象到option上 – 不仅仅是字符串。这时候你需要设置这个对象的那个属性作为drop-down列表或multi-select列表的text来显示。例如,例3中使用的是设置额外的参数optionsText将对象的属性名countryName作为显示的文本。

如果不想仅仅显示对象的属性值作为每个item项的text值,那你可以设置optionsText 为JavaScript 函数,然后再函数里通过自己的逻辑返回相应的值(该函数参数为item项本身)。例4展示的就是返回item的2个属性值合并的结果。

 

optionsValue

和optionsText类似, 你也可以通过额外参数optionsValue来声明对象的那个属性值作为该<option>的value值。

经典场景:如在更新options的时候想保留原来的已经选择的项。例如,当你重复多次调用Ajax获取car列表的时候,你要确保已经选择的某个car一直都是被选择上,那你就需要设置optionsValue为“carId”或者其它的unique标示符,否则的话KO找不知道之前选择的car是新options里的哪一项。

 

selectedOptions

对于multi-select列表,你可以用selectedOptions读取和设置多个选择项。技术上看它是一个单独的绑定,有自己的文档,请参考: selectedOptions绑定。

 

注:已经被选择的项会再options改变的时候保留

当使用options绑定<select>元素的时候,如果options改变,KO将尽可能第保留之前已经被选择的项不变(除非是你事先手工删除一个或多个已经选择的项)。这是因为options 绑定尝试依赖value值的绑定(single-select列表)和selectedOptions绑定(multi-select列表)。

 

依赖性

除KO核心类库外,无依赖。

#p#

 

15 selectedOptions 绑定

目的

selectedOptions绑定用于控制multi-select列表已经被选择的元素,用在使用options绑定的<select>元素上。

当用户在multi-select列表选择或反选一个项的时候,会将view model的数组进行相应的添加或者删除。同样,如果view model上的这个数组是observable数组的话,你添加或者删除任何item(通过push或者splice)的时候,相应的UI界面里的option项也会被选择上或者反选。这种方式是2-way绑定。

注:控制single-select下拉菜单选择项,你可以使用value绑定。

 

例子

  1. <p> 
  2.     Choose some countries you'd like to visit:  
  3.     <select data-bind="options: availableCountries, selectedOptions: chosenCountries" size="5" multiple="true"></select> 
  4. </p> 
  5.  
  6. <script type="text/javascript"> 
  7.     var viewModel = {  
  8.         availableCountries: ko.observableArray(['France', 'Germany', 'Spain']),  
  9.         chosenCountries: ko.observableArray(['Germany']) // Initially, only Germany is selected  
  10.     };   
  11.  
  12.     // ... then later ...  
  13.     viewModel.chosenCountries.push('France'); // Now France is selected too  
  14. </script> 

参数

主参数

该参数是数组(或observable数组)。KO设置元素的已选项为和数组里match的项,之前的已选择项将被覆盖。

如果参数是依赖监控属性observable数组,那元素的已选择项selected options项将根据参数值的变化(通过push,pop,或其它observable数组方法)而更新,如果不是,那元素的已选择项selected options将只设置一次并且以后不在更新。

不管该参数是不是observable数组,用户在multi-select列表里选择或者反选的时候,KO都会探测到,并且更新数组里的对象以达到同步的结果。这样你就可以获取options已选项。

其它参数

 

注:支持让用户选择任意JavaScript对象

在上面的例子里,用户可以选择数组里的字符串值,但是选择不限于字符串,如果你愿意你可以声明包含任意JavaScript对象的数组,查看options绑定如何显示JavaScript对象到列表里。

这种场景,你可以用selectedOptions来读取或设置这些对象本身,而不是页面上显示的option表示形式,这样做在大部分情况下都非常清晰。view model就可以探测到你从数组对象里选择的项了,而不必关注每个项和页面上展示的option项是如何map的。

 

依赖性

除KO核心类库外,无依赖。

 

16 uniqueName 绑定

目的

uniqueName绑定确保所绑定的元素有一个非空的name属性。如果该元素没有name属性,那绑定会给它设置一个unique的字符串值作为name属性。你不会经常用到它,只有在某些特殊的场景下才用到,例如:

◆ 在使用KO的时候,一些技术可能依赖于某些元素的name属性,尽快他们没有什么意义。例如,jQuery Validation验证当前只验证有name属性的元素。为配合Knockout UI使用,有些时候需要使用uniqueName绑定避免让jQuery Validation验证出错。

◆ IE 6下,如果radio button没有name属性是不允许被checked了。大部分时候都没问题,因为大部分时候radio button元素都会有name属性的作为一组互相的group。不过,如果你没声明,KO内部会在这些元素上使用uniqueName那么以确保他们可以被checked。
 

例子

  1. <input data-bind="value: someModelProperty, uniqueName: true"/> 

 

参数

主参数

就像上面的例子一样,传入true(或者可以转成true的值)以启用uniqueName绑定。

其它参数

 

依赖性

除KO核心类库外,无依赖。

原文:http://www.cnblogs.com/TomXu/archive/2011/11/24/2256904.html

【系列文章】

Knockout应用开发指南之入门介绍

Knockout应用开发指南之监控属性(Observables)

责任编辑:陈贻新 来源: 汤姆大叔的博客
相关推荐

2011-12-05 14:50:13

Knockout

2011-12-05 15:02:21

Knockout

2011-11-29 16:38:58

Knockout

2011-12-05 15:44:45

Knockout

2012-01-04 16:21:11

2011-11-29 16:56:30

Knockout

2012-01-04 16:11:49

Knockout

2011-04-15 14:22:20

图片操作UIBlackBerry

2011-04-18 11:00:34

使用音频BlackBerry

2023-12-26 08:12:14

LCEL语法异步

2011-06-07 09:10:41

BlackBerry 开发

2011-04-15 15:16:28

使用图像对象画图BlackBerry

2022-08-02 08:01:09

开发插件Chrome前端技术

2011-07-25 16:21:22

Sencha touc

2011-04-15 16:05:00

监听UI对象的改变BlackBerry

2009-06-24 16:30:21

JSF组件模型

2012-03-26 09:27:40

谷歌安卓开发谷歌安卓

2011-06-09 18:24:36

QT Wince

2023-05-15 18:44:07

前端开发

2021-10-11 08:37:14

鸿蒙HarmonyOS应用
点赞
收藏

51CTO技术栈公众号