KnockoutJS 3.X API 第三章 计算监控属性(2) 可赋值的计算监控属性
可赋值的计算监控属性
可赋值的计算监控属性是非常专业的,大多数情况下一般用不到,初学者可以跳过这一节
通常情况下,计算监控属性一般情况下是只读的。我们可以通过使用自己的回调函数让计算监控属性变为可赋值状态。
您可以用自己的定制逻辑让计算监控属性可写。就像将空属性,可以使用一个模型对象的链接的语法进行赋值。例如,myViewModel.fullName('Joe Smith').age(50)
。
示例1:分解用用户输入
让我们回到经典的例子“名+姓=全名”例如,fullName是计算监控属性,用户可以直接编辑全名,再根据用户输入的全名解析并将值分别赋值给firstName和lastName这两个监控属性。
UI源码:
<div>First name: <span data-bind="text: firstName"></span></div> <div>Last name: <span data-bind="text: lastName"></span></div> <div class="heading">Hello, <input data-bind="textInput: fullName"/></div>
视图模型代码:
function MyViewModel() { this.firstName = ko.observable('Planet'); this.lastName = ko.observable('Earth'); this.fullName = ko.pureComputed({ read: function () { return this.firstName() + " " + this.lastName(); }, write: function (value) { var lastSpacePos = value.lastIndexOf(" "); if (lastSpacePos > 0) { // Ignore values with no space character this.firstName(value.substring(0, lastSpacePos)); // Update "firstName" this.lastName(value.substring(lastSpacePos + 1)); // Update "lastName" } }, owner: this }); } ko.applyBindings(new MyViewModel());
本例中,使用了pureComputed(当然也可以使用Computed)的read和write回掉函数,其中write回掉函数将计算监控属性进行解析,并分别赋值给firstName和lastName这两个监控属性。
示例2:全选或取消全选项目
当使用复选框来选择项目的时候需要包括全选或取消全选的所有项目的方法。
UI源码:
<div class="heading"> <input type="checkbox" data-bind="checked: selectedAllProduce" title="Select all/none"/> Produce </div> <div data-bind="foreach: produce"> <label> <input type="checkbox" data-bind="checkedValue: $data, checked: $parent.selectedProduce"/> <span data-bind="text: $data"></span> </label> </div>
视图模型源码:
function MyViewModel() { this.produce = [ 'Apple', 'Banana', 'Celery', 'Corn', 'Orange', 'Spinach' ]; this.selectedProduce = ko.observableArray([ 'Corn', 'Orange' ]); this.selectedAllProduce = ko.pureComputed({ read: function () { // Comparing length is quick and is accurate if only items from the // main array are added to the selected array. return this.selectedProduce().length === this.produce.length; }, write: function (value) { this.selectedProduce(value ? this.produce.slice(0) : []); }, owner: this }); } ko.applyBindings(new MyViewModel());
示例3:值转换器
有时候,可能界面上的值并非是要传递到数据库中的值。例如,您可能希望存储原始浮点值,但是在用户编辑的时候让他跟一个货币符号。可以通过如下方式来进行转换:
UI源码:
<div>Enter bid price: <input data-bind="textInput: formattedPrice"/></div> <div>(Raw value: <span data-bind="text: price"></span>)</div>
视图模型源码:
function MyViewModel() { this.price = ko.observable(25.99); this.formattedPrice = ko.pureComputed({ read: function () { return '$' + this.price().toFixed(2); }, write: function (value) { // Strip out unwanted characters, parse as float, then write the // raw data back to the underlying "price" observable value = parseFloat(value.replace(/[^\.\d]/g, "")); this.price(isNaN(value) ? 0 : value); // Write to underlying storage }, owner: this }); } ko.applyBindings(new MyViewModel());
现在,只要用户进入一个新的价格,文本框会立即更新,以显示货币符号和两位小数格式,这是一种很好的用户体验,就算用户多输入几位小数,多出两位小数的部分也会被自动删除。同样,它们不能输入负值,因为write回掉函数会去掉
任何减号。
示例4:筛选和验证用户输入
在示例1中,描述了如何编写可赋值的计算监控属性,但是如果用户在不输入空格的情况下,将会出现LastName不被赋值的情况。
本例中,将使用KO的验证机制,保证在用户输入无效值的时候给出错误提示:
UI源码:
<div>Enter a numeric value: <input data-bind="textInput: attemptedValue"/></div> <div class="error" data-bind="visible: !lastInputWasValid()">That's not a number!</div> <div>(Accepted value: <span data-bind="text: acceptedNumericValue"></span>)</div>
视图模型源码:
function MyViewModel() { this.acceptedNumericValue = ko.observable(123); this.lastInputWasValid = ko.observable(true); this.attemptedValue = ko.pureComputed({ read: this.acceptedNumericValue, write: function (value) { if (isNaN(value)) this.lastInputWasValid(false); else { this.lastInputWasValid(true); this.acceptedNumericValue(value); // Write to underlying storage } }, owner: this }); } ko.applyBindings(new MyViewModel());
如上述源码,acceptedNumericValue
将只包含数值,如果键入其他任何值都会触发一个验证消息,而不更新的UI界面的acceptedNumericValue
。
总结
对于上述示例,有些时候可能使用Jquery验证会更加简单便利,有些时候可能KO的计算监控属性验证更加简单,这需要你视情况而选择某种技术来解决问题。大多数新情况下都是配合KO和Jquery使用,上述示例只是描述一下KO的这些机制作用。切勿生搬硬套。要灵活运用。