<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.0/jquery.min.js"></script> <script type="text/javascript" src="jslib/jquery.tmpl.min.js"></script> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <h3>Meal upgrades</h3> <p>Make your flight more bearable by selecting a meal to match your social and economic status.</p> Chosen meal: <select data-bind="options: availableMeals, optionsText: 'mealName', value: chosenMeal"></select> <p> You've chosen: <b data-bind="text: chosenMeal().description"></b> (price: <span data-bind='text: formatPrice(chosenMeal().extraCost)'></span>) </p> <script type="text/javascript"> var availableMeals = [ { mealName: 'Standard', description: 'Dry crusts of bread', extraCost: 0 }, { mealName: 'Premium', description: 'Fresh bread with cheese', extraCost: 9.95 }, { mealName: 'Deluxe', description: 'Caviar and vintage Dr Pepper', extraCost: 18.50 } ]; var viewModel = { chosenMeal: ko.observable(availableMeals[0]) }; ko.applyBindings(viewModel); function formatPrice(price) { return price == 0 ? "Free" : "$" + price.toFixed(2); } </script> </body> </html>
1.可以直接绑定viewModel之外的变量。
2.data-bind标签内可以直接调用JavaScript方法。
visible 绑定
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>绑定visible</title> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <div data-bind="visible: shouldShowMessage"> You will see this message only when "shouldShowMessage" holds a true value. </div> <button type="button" onclick="clickHandler();" data-bind="text: btn_title"></button> <script type="text/javascript"> const STR_SHOW = "显示", STR_HIDE = "隐藏"; var viewModel = { btn_title: ko.observable(STR_HIDE), shouldShowMessage: ko.observable(true) }; ko.applyBindings(viewModel); function clickHandler() { viewModel.shouldShowMessage(!viewModel.shouldShowMessage()); viewModel.btn_title(viewModel.shouldShowMessage() ? STR_HIDE : STR_SHOW); } </script> </body> </html>
<div data-bind="visible: myValues().length > 0"> You will see this message only when 'myValues' has at least one member. </div> <script type="text/javascript"> var viewModel = { myValues: ko.observableArray([]) // Initially empty, so message hidden }; viewModel.myValues.push("some value"); // Now visible ko.applyBindings(viewModel); </script>
html 绑定
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <div data-bind="html: details"></div> <script type="text/javascript"> var viewModel = { details: ko.observable() // Initially blank }; viewModel.details("<em>For further details, view the report <a href='report.html'>here</a>.</em>"); // HTML content appears ko.applyBindings(viewModel); </script> </body> </html>
css 绑定
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> <style type="text/css"> .abc {background-color:#ffccfc} </style> </head> <body> <div data-bind="css: { 'abc': currentProfit > 0 }"> Profit Information </div> <script type="text/javascript"> var viewModel = { currentProfit: ko.observable(100) }; // viewModel.currentProfit(-50); ko.applyBindings(viewModel); </script> </body> </html>
style 绑定
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> <style type="text/css"> .abc {background-color:#ffccfc} </style> </head> <body> <div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black' }"> Profit Information </div> <script type="text/javascript"> var viewModel = { currentProfit: ko.observable(150000) // Positive value, so initially black }; viewModel.currentProfit(-50); ko.applyBindings(viewModel); </script> </body> </html>
<div data-bind="style: { color: currentProfit() < 0 ? 'red' : 'black', fontWeight: isSevere() ? 'bold' : '' }">...</div>
注:应用的style的名字不是合法的JavaScript变量命名
如果你需要应用font-weight或者text-decoration,你不能直接使用,而是要使用style对应的JavaScript名称。
错误: { font-weight: someValue }; 正确: { fontWeight: someValue }
错误: { text-decoration: someValue }; 正确: { textDecoration: someValue }
参考:style名称和对应的JavaScript 名称列表。
attr 绑定
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <a data-bind="attr: { href: url, title: details }, text: details"> Report </a> <script type="text/javascript"> var viewModel = { url: ko.observable("year-end.html"), details: ko.observable("Report including final year-end statistics") }; ko.applyBindings(viewModel); const ruleArr = ["http://www.baidu.com/", "http://www.163.com/"]; const detailsArr = ["百度", "网易"]; function run(){ var idx = 0; setInterval(function(){ viewModel.url(ruleArr[idx%ruleArr.length]); viewModel.details(detailsArr[idx++%ruleArr.length]); console.log(viewModel.url(), viewModel.details()); }, 1000); } run(); </script> </body> </html>
注:应用的属性名字不是合法的JavaScript变量命名
<!--错误写法--> <div data-bind="attr: { data-something: someValue }">...</div> <!--正确写法--> <!--因为data-something 不是一个合法的命名。解决方案是:在data-something两边加引号作为一个字符串使用。这是一个合法的JavaScript 对象 文字(从JSON技术规格说明来说,你任何时候都应该这样使用,虽然不是必须的)。--> <div data-bind="attr: { ‘data-something’: someValue }">...</div>
click 绑定
click绑定在DOM元素上添加事件句柄以便元素被点击的时候执行定义的JavaScript 函数。大部分是用在button,input和连接a上,但是可以在任意元素上使用。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <div> You've clicked <span data-bind="text: numberOfClicks"></span> times <button data-bind="click: incrementClickCounter">Click me</button> <button data-bind="click: clearClickCounter">Clear</button> </div> <script type="text/javascript"> var viewModel = { numberOfClicks: ko.observable(0), incrementClickCounter: function () { var previousCount =this.numberOfClicks(); this.numberOfClicks(previousCount +1); }, clearClickCounter: function () { this.numberOfClicks(0); } }; ko.applyBindings(viewModel); </script> </body> </html>
Click点击事件时所执行的函数。
你可以声明任何JavaScript函数 – 不一定非要是view model里的函数。你可以声明任意对象上的任何函数,例如: someObject.someFunction。
View model上的函数在用的时候有一点点特殊,就是不需要引用对象的,直接引用函数本身就行了,比如直接写incrementClickCounter 就可以了,而无需写成:viewModel.incrementClickCounter(尽管是合法的)。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <!--创建句柄并传递参数给你的方法--> <button data-bind="click: function() { viewModel.myFunction('hello', 'world') }"> Click me </button> <script type="text/javascript"> var viewModel = { myFunction: function(a, b){ console.log(a + " " + b); } }; ko.applyBindings(viewModel); </script> </body> </html>
控制this句柄
使用匿名函数的时候没有具体的要求,因为JavaScript代码 someObject.someFunction()就意味着调用someFunction,然后设置this到 someObject对象上。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!-- 如果不适用bind,go方法内无法访问到obj.num --> <button type="button" data-bind="click: obj.go.bind(obj)">GO</button> <script type="text/javascript"> var obj = { num: 123456, go: function(){ console.log("run fun go:" + this.num); } } ko.applyBindings(new Object()); </script> </body> </html>
防止事件冒泡
默认情况下,Knockout允许click事件继续在更高一层的事件句柄上冒泡执行。例如,如果你的元素和父元素都绑定了click事件,那当你点击该元素的时候两个事件都会触发的。如果需要,你可以通过额外的绑定clickBubble来禁止冒泡。
<div data-bind="click: myDivHandler"> <button data-bind="click: myButtonHandler, clickBubble: false"> Click me </button> </div>
默认情况下,myButtonHandler会先执行,然后会冒泡执行myDivHandler。但一旦你设置了clickBubble为false的时候,冒泡事件会被禁止。
event 绑定
event绑定在DOM元素上添加指定的事件句柄以便元素被触发的时候执行定义的JavaScript 函数。大部分情况下是用在keypress,mouseover和mouseout上
你需要传入的是一个JavaScript对象,他的属性名是事件名称,值是你所需要执行的函数。
你可以声明任何JavaScript函数 – 不一定非要是view model里的函数。你可以声明任意对象上的任何函数,例如: event: { mouseover: someObject.someFunction }。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <script type="text/javascript" src="jslib/knockout-2.2.0.js"></script> </head> <body> <div> <div data-bind="event: { mouseover: enableDetails, mouseout: disableDetails }"> Mouse over me </div> <div data-bind="visible: detailsEnabled"> Details </div> </div> <script type="text/javascript"> var viewModel = { detailsEnabled: ko.observable(false), enableDetails: function () { this.detailsEnabled(true); }, disableDetails: function () { this.detailsEnabled(false); } }; ko.applyBindings(viewModel); </script> </body> </html>
允许执行默认事件
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>绑定event</title> </head> <body> <input data-bind="value: v, event: {keypress: keypressHandler}"> <script type="text/javascript"> var viewModel = { v : ko.observable(), keypressHandler: function(obj, event){ //如果不return true,keypress的默认事件不会执行,文本框讲不显示任何内容 return true; } } ko.applyBindings(viewModel); </script> </body> </html>
submit 绑定
submit绑定在form表单上添加指定的事件句柄以便该form被提交的时候执行定义的JavaScript 函数。只能用在表单form元素上。
当你使用submit绑定的时候, Knockout会阻止form表单默认的submit动作。换句话说,浏览器会执行你定义的绑定函数而不会提交这个form表单到服务器上。可以很好地解释这个,使用submit绑定就是为了处理view model的自定义函数的,而不是再使用普通的HTML form表单。如果你要继续执行默认的HTML form表单操作,你可以在你的submit句柄里返回true。
为什么不在submit按钮上使用click绑定?
在form上,你可以使用click绑定代替submit绑定。不过submit可以handle其它的submit行为,比如在输入框里输入回车的时候可以提交表单
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>submit</title> </head> <body> <form data-bind="submit: doSomething"> ... form contents go here ... <button type="submit">Submit</button> </div> <script type="text/javascript"> var viewModel = { doSomething: function (formElement) { console.dir(formElement); } }; ko.applyBindings(viewModel); </script> </body> </html>
enable 绑定
enable绑定使DOM元素只有在参数值为 true的时候才enabled。在form表单元素input,select,和textarea上非常有用。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>enable</title> </head> <body> <p> <input type='checkbox' data-bind="checked: hasCellphone"/> I have a cellphone </p> <p> Your cellphone number: <input type='text' data-bind="value: cellphoneNumber, enable: hasCellphone"/> </p> <script type="text/javascript"> var viewModel = { hasCellphone: ko.observable(false), cellphoneNumber: "" }; ko.applyBindings(viewModel); </script> </body> </html>
disable 绑定
disable绑定使DOM元素只有在参数值为 true的时候才disabled。在form表单元素input,select,和textarea上非常有用。
disable绑定和enable绑定正好相反,详情请参考enable绑定。
12 value 绑定
目的
value绑定是关联DOM元素的值到view model的属性上。主要是用在表单控件<input>,<select>和<textarea>上。
当用户编辑表单控件的时候, view model对应的属性值会自动更新。同样,当你更新view model属性的时候,相对应的元素值在页面上也会自动更新。
注:如果你在checkbox或者radio button上使用checked绑定来读取或者写入元素的 checked状态,而不是value 值的绑定。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>value</title> </head> <body> <p>Login name: <input data-bind="value: userName"/></p> <p>Password: <input type="password" data-bind="value: userPassword"/></p> <script type="text/javascript"> var viewModel = { userName: ko.observable(""), // Initially blank userPassword: ko.observable("abc"), // Prepopulate }; ko.applyBindings(viewModel); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>value</title> </head> <body> <p>Your value: <input data-bind="value: someValue, valueUpdate: 'afterkeydown'"/></p> <p>You have typed: <span data-bind="text: someValue"></span></p> <!-- updates in real-time --> <script type="text/javascript"> var viewModel = { someValue: ko.observable("edit me") }; ko.applyBindings(viewModel); </script> </body> </html>
参数
主参数
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:绑定下拉菜单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,不是真正的绑定。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>2way</title> </head> <body> <p>First value: <input data-bind="value: firstValue, valueUpdate: 'afterkeydown'"/></p> <!-- two-way binding --> <p>Second value: <input data-bind="value: secondValue"/></p> <!-- one-way binding --> <p>Third value: <input data-bind="value: secondValue.length"/></p> <!-- no binding --> <p>First.length: <span data-bind="text: firstValue"/></p> <script type="text/javascript"> var viewModel = { firstValue: ko.observable("hello"), // Observable secondValue: "hello, again"// Not observable }; ko.applyBindings(viewModel); </script> </body> </html>
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绑定。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>redio buttons</title> </head> <body> <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p> <div data-bind="visible: wantsSpam"> Preferred flavor of spam: <div><input type="radio" name="flavorGroup" value="cherry" data-bind="checked: spamFlavor"/> Cherry</div> <div><input type="radio" name="flavorGroup" value="almond" data-bind="checked: spamFlavor"/> Almond</div> <div><input type="radio" name="flavorGroup" value="msg" data-bind="checked: spamFlavor"/> Monosodium Glutamate</div> </div> <script type="text/javascript"> var viewModel = { wantsSpam: ko.observable(true), spamFlavor: ko.observable("almond") // Initially selects only the Almond radio button }; ko.applyBindings(viewModel); var go = function(){ var idx = 0; const cfg = ["cherry", "almond", "msg"]; setInterval(function(){ viewModel.spamFlavor(cfg[idx++%cfg.length]); }, 500); }; go(); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>checked</title> </head> <body> <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p> <div data-bind="visible: wantsSpam"> Preferred flavors of spam: <div><input type="checkbox" value="cherry" data-bind="checked: spamFlavors"/> Cherry</div> <div><input type="checkbox" value="almond" data-bind="checked: spamFlavors"/> Almond</div> <div><input type="checkbox" value="msg" data-bind="checked: spamFlavors"/> Monosodium Glutamate</div> </div> <script type="text/javascript"> var viewModel = { wantsSpam: ko.observable(true), spamFlavors: ko.observableArray(["cherry", "almond"]) // Initially checks the Cherry and Almond checkboxes }; // ... then later ... //viewModel.spamFlavors.push("msg"); // Now additionally checks the Monosodium Glutamate checkbox ko.applyBindings(viewModel); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>checked</title> </head> <body> <p>Send me spam: <input type="checkbox" data-bind="checked: wantsSpam"/></p> <script type="text/javascript"> var viewModel = { wantsSpam: ko.observable(false) // Initially checked }; ko.applyBindings(viewModel); </script> </body> </html>
参数
主参数
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值将只设置一次并且以后不在更新。
14 options 绑定
目的
options绑定控制什么样的options在drop-down列表里(例如:<select>)或者 multi-select 列表里 (例如:<select size='6'>)显示。此绑定不能用于<select>之外的元素。关联的数据应是数组(或者是observable数组),<select>会遍历显示数组里的所有的项。
注:对于multi-select列表,设置或者获取选择的多项需要使用selectedOptions绑定。对于single-select列表,你也可以使用value绑定读取或者设置元素的selected项。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>Drop-down list</title> </head> <body> <p>Destination country: <select data-bind="options: availableCountries"></select></p> <script type="text/javascript"> var viewModel = { availableCountries: ko.observableArray(['France', 'Germany', 'Spain']) // These are the initial options }; // ... then later ... viewModel.availableCountries.push('China'); // Adds another option ko.applyBindings(viewModel); </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>Multi-select list</title> </head> <body> <p>Choose some countries you'd like to visit: <select data-bind="options: availableCountries" size="5" multiple="true"></select></p> <script type="text/javascript"> var viewModel = { availableCountries: ko.observableArray(['France', 'Germany', 'Spain']) }; // ... then later ... viewModel.availableCountries.push('China'); // Adds another option ko.applyBindings(viewModel); </script> </body> </html>
参数
主参数
该参数是一个数组(或者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核心类库外,无依赖。
15 selectedOptions 绑定
目的
selectedOptions绑定用于控制multi-select列表已经被选择的元素,用在使用options绑定的<select>元素上。
当用户在multi-select列表选择或反选一个项的时候,会将view model的数组进行相应的添加或者删除。同样,如果view model上的这个数组是observable数组的话,你添加或者删除任何item(通过push或者splice)的时候,相应的UI界面里的option项也会被选择上或者反选。这种方式是2-way绑定。
注:控制single-select下拉菜单选择项,你可以使用value绑定。
<!DOCTYPE html> <html lang="en"> <head> <script type="text/javascript" src="libs/knockout-3.4.0.js"></script> <meta charset="UTF-8"> <title>Multi-select list</title> </head> <body> <p> Choose some countries you'd like to visit: <select data-bind="options: availableCountries, selectedOptions: chosenCountries" size="5" multiple="true"></select> </p> <script type="text/javascript"> var viewModel = { availableCountries: ko.observableArray(['France', 'Germany', 'Spain']), chosenCountries: ko.observableArray(['Germany']) // Initially, only Germany is selected }; // ... then later ... viewModel.chosenCountries.push('France'); // Now France is selected too ko.applyBindings(viewModel); </script> </body> </html>
参数
主参数
该参数是数组(或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
<input data-bind="value: someModelProperty, uniqueName: true"/>
参数
主参数
就像上面的例子一样,传入true(或者可以转成true的值)以启用uniqueName绑定。
其它参数
无