iuap-design/blog

KO 的计算属性 computed 中篇

Opened this issue · 0 comments

属性的可写

上篇我们介绍了属性的可读,怎么可能让计算属性变的可写,你只需要提供一个回调函数来实现值的写入。然后你可以把这个可写的计算属性当成一个普通的监控属性来使用,通过你自定义的逻辑来实现它的读和写。这个强大的功能可以拓宽我们对KO的使用范围,你可以通过链式语法在一个View Model上传入多个监控属性或者计算属性。

myViewModel.fullName('Joe Smith').age(50)

示例一:分解用户输入

返回到前面经典的“first name + last name = full name” 示例,你可以在返回全名之前,使fullName计算属性变得可写,所以用户可以直接编辑全名,而程序可以将其输入的值进行解析并映射到底层绑定到firstName和lastName监控属性上。

function MyViewModel() {
    this.firstName = ko.observable('Planet');
    this.lastName = ko.observable('Earth');
    this.fullName = ko.computed({
        read: function () { },
        write: function (value) {
            var lastSpacePos = value.lastIndexOf(" ");
            if (lastSpacePos > 0) {
                // 获取firstName
                this.firstName(value.substring(0, lastSpacePos));
                // 获取lastName
                this.lastName(value.substring(lastSpacePos + 1));
            }
        }, owner: this
    });
}
ko.applyBindings(new MyViewModel());

在这个例子当中,write回调事件来处理用户输入的值将其分解成“firstName”和“lastName”两个部分,并将这些值返回到底层监控属性上.

下面是dom绑定

<p>Firstname:<span data-bind="text: firstName"></span></p>
<p>Lastname:<span data-bind="text: lastName"></span></p>
<h2>Hello,<input data-bind="value: fullName"/>!</h2>

在这里“firstName”和“lastName”是不可编辑而全名可编辑的。前面的 view model代码只用到了一个参数进行初始化计算属性.

示例二:值转换

有时你可能需要对底层存储的一个数据进行简单的转换之后显示给用户,多用于表单校验。

return this.firstName()+" "+this.lastName();
function MyViewModel(){
    this.price=ko.observable(25.99);
    this.formattedPrice=ko.computed({
        read:function(){
            return'$'+this.price().toFixed(2);   },
        write:function(value){
            //   解析成两位数的浮点类型
            value=parseFloat(value.replace(/[^\.\d]/g,""));
            //  如果价格为空,则自动设置成0
            this.price(isNaN(value)?0:value);
        },    owner:this });}
ko.applyBindings(new MyViewModel());   

<p>Enter bid price:<inputdata-bind="value: formattedPrice"/></p>

输入不符合规范的价格都会被解析成小数点后有两位的数字

示例三:筛选和验证用户输入

及时的校验提示

function MyViewModel() {
    this.acceptedNumericValue = ko.observable(123);
    this.lastInputWasValid = ko.observable(true);
    this.attemptedValue = ko.computed({
        read: this.acceptedNumericValue,
        write: function (value) {
            if (isNaN(value))
                this.lastInputWasValid(false);
            else {
                this.lastInputWasValid(true);
                this.acceptedNumericValue(value);
            }
        }, owner: this
    });
}
ko.applyBindings(new MyViewModel());


<p>Enter a numeric value:<inputdata-bind="value: attemptedValue"/></p>
<divdata-bind="visible: !lastInputWasValid()">That's not a number!</div>

任何其他输入的值将触发显示验证消息