我是淘汰赛的新手,我想弄清楚如何把两件我理解的东西放在一起。
我需要:
示例:
startTime
,在几秒钟内duration
,stopTime
从startTime + duration
startTime
无法更改duration
和stopTime
与输入字段相关联stopTime
并以HH:MM:SS
格式stopTime
,则应计算duration
并自动更新duration
,则应计算stopTime
并自动更新我可以让它们相互更新(假设Sec2HMS
和HMS2Sec
在别处定义,并在HH:MM:SS
和秒之间转换):
this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);
// This dependency works by itself.
this.stopTimeFormatted = ko.computed({
read: function () {
return Sec2HMS(this.startTime + parseInt(this.duration()), true);
},
write: function (value) {
var stopTimeSeconds = HMS2Sec(value);
if (!isNaN(stopTimeSeconds)) {
this.duration(stopTimeSeconds - this.startTime);
} else {
this.duration(0);
}
},
owner: this
});
或者,我可以使用extenders
或fn
验证输入,如淘汰文档中所示:
ko.subscribable.fn.HMSValidate = function (errorMessage) {
//add some sub-observables to our observable
var observable = this;
observable.hasError = ko.observable();
observable.errorMessage = ko.observable();
function validate(newValue) {
var isInvalid = isNaN(HMS2Sec(newValue));
observable.hasError(isInvalid ? true : false);
observable.errorMessage(isInvalid ? errorMessage : null);
}
//initial validation
validate(observable());
//validate whenever the value changes
observable.subscribe(validate);
//return the original observable
return observable;
};
this.startTime = 120; // Start at 120 seconds
this.duration = ko.observable(0);
this.stopTimeHMS = ko.observable("00:00:00").HMSValidate("HH:MM:SS please");
但我如何让他们一起工作?如果我将HMSValidate
添加到第一个块中的计算中,则它不起作用,因为当HMSValidate
的{{1}}函数获取值时,它已经被更改。
我已经通过添加另一个observable来在第一个块中工作,该observable跟踪传递给计算器的“原始”值,然后添加另一个使用该值来计算它是否是错误状态的计算器,但是感觉不是很优雅。
有更好的方法吗?
答案 0 :(得分:2)
经过一周的回收问题后,我回到了这个问题,我没有找到解决方法(代码清理时间!),这就是我所拥有的。
我最终提出了我在问题的最后提到的想法,但将其封装在fn本身中。
ko.subscribable.fn.hmsValidate = function (errorMessage) {
var origObservable = this;
var rawValue = ko.observable(origObservable()); // Used for error checking without changing our main observable.
if (!origObservable.hmsFormatValidator) {
// Handy place to store the validator observable
origObservable.hmsFormatValidator = ko.computed({
read: function () {
// Something else could have updated our observable, so keep our rawValue in sync.
rawValue(origObservable());
return origObservable();
},
write: function (newValue) {
rawValue(newValue);
if (newValue != origObservable() && !isNaN(HMS2Sec(newValue))) {
origObservable(newValue);
}
}
});
origObservable.hmsFormatValidator.hasError = ko.computed(function () {
return isNaN(HMS2Sec(rawValue()));
}, this);
origObservable.hmsFormatValidator.errorMessage = ko.computed(function () {
return errorMessage;
}, this);
}
return origObservable.hmsFormatValidator;
};
这样做会创建另一个计算的observable,它作为原始observable的前置/过滤器。该observable有一些其他子可观察对象hasError
和errorMessage
,它们附加了错误状态。 rawValue
跟踪输入的值,以便我们可以检测它是否是一个好的值。这可以处理我的一半要求。
至于使两个值相互依赖,我问题中的原始代码有效。为了验证它,我向它添加hmsValidate
,如下所示:
this.stopTimeFormatted = ko.computed({
read: function () {
return Sec2HMS(this.startTime + parseInt(this.duration()), true);
},
write: function (value) {
this.duration(HMS2Sec(value) - this.startTime);
},
owner: this
}).hmsValidate("HH:MM:SS please");
在此处查看此行动:http://jsfiddle.net/cygnl7/tNV5S/1/
值得注意的是,write
内部的验证不再是必需的,因为只有hmsValidate
才能正确验证该值。
这对我来说仍然感觉有点不雅,因为我正在检查isNaN几次并且必须跟踪原始值(特别是在read()中),所以如果有人想出另一种方法来做到这一点,我全是耳朵。