[英]Knockout Nested Object Scoping Undefined Reference
我正在尝试使用KnockoutJS使用以下代码编写基本表单:
var Form = function() {
var self = this;
self.name = {
value: ko.observable(""),
isValid: ko.computed(function () {
return self.name.value().length > 0;
}),
},
self.email = {
value: ko.observable(""),
isValid: ko.computed(function () {
return false;
})
},
self.message = {
value: ko.observable(""),
isValid: ko.computed(function () {
return false;
})
},
self.isValid = ko.computed(function () {
return self.name.isValid && self.email.isValid && self.message.isValid;
})
};
但是,当我尝试运行此代码时,出现以下错误: Unable to get property 'value' of undefined or null reference
。 在我看来,这似乎是一个范围问题,但是我对淘汰赛还不够熟悉,无法理解为什么会这样。 没有Knockout,我似乎能够使此代码正常工作(用true替代isValid的值和函数,将所有可观察对象替换为true),但是我希望实时更新这些值。 我总是可以将验证功能与顶级功能分开,但这似乎是不合适的方法。 每个表单字段都有一个值,并且它是自己唯一的验证,因此,使每个表单字段都具有两个属性成为自己的对象是有意义的。
任何帮助或指导表示赞赏。
这个
self.name = {
value: ko.observable(""),
isValid: ko.computed(function () {
return self.name.value().length > 0;
}),
},
不起作用,因为内部函数(计算的回调)引用了self.name
,甚至尚未完全定义。 由于computes被立即调用,因此您会看到一个错误。
您可以使用deferEvaluation
选项来延迟对计算的isValid
求值,直到实际请求其值为止:
self.name = {
value: ko.observable(""),
isValid: ko.computed({
read: function () { return self.name.value().length > 0; },
deferEvaluation: true
}),
},
那会行得通,但也很快就会变得重复和笨拙。
作为替代方案,您可以使用Knockout 扩展程序以抽象/解耦的方式使可观察的Validatatable可用。
ko.extenders.validator = function (target, validationCallback) {
// create an isValid property on the target observable,
// immediately calculate validity of its current value
target.isValid = ko.observable(validationCallback(target()));
// subscribe to future changes
target.subscribe(function (newValue) {
target.isValid(validationCallback(newValue));
});
// return target observable for chaining
return target;
};
现在,在定义了该扩展器之后,您要做的就是创建回调函数来验证值并返回true或false。
var Form = function () {
var self = this;
self.name = ko.observable("").extend({
validator: function (value) { return value.length > 0; }
});
self.email = ko.observable("").extend({
validator: function (value) { return true; }
});
self.message = ko.observable("").extend({
validator: function (value) { return true; }
});
self.isValid = ko.computed(function () {
var overallValid = true;
ko.utils.objectForEach(self, function (key, value) {
if (value.hasOwnProperty("isValid")) {
overallValid = overallValid && value.isValid();
}
});
return overallValid;
});
};
现在,进一步分离验证功能变得非常简单:
var validators = {
email: function (value) { return /* email check here */; },
minLen: function (minLen) {
return function (value) { return value.length >= minLen; }
},
maxLen: function (maxLen) {
return function (value) { return value.length <= maxLen; }
},
minmaxLen: function (minLen, maxLen) {
return function (value) { return value.length >= minLen && value.length <= maxLen; }
},
matches: function (regex) {
return function (value) { return regex.test(value); }
}
}
和
self.name = ko.observable("").extend({ validator: validators.minLen(1) });
self.age = ko.observable("").extend({ validator: validators.matches(/^\d+$/) });
您会发现,当然有人已经做了所有这一切 (还有更多)。
最好为每个对象创建单独的函数:
var Form = function() {
var self = this;
self.name = new NameFormField();
}
var NameFormField = function() {
var self = this;
self.value = ko.observable("");
self.isValid = ko.computed(function () {
//not sure why you are checking length here
return self.value().length > 0;
});
}
您可以使它工作的另一种方法是:
var Form = function() {
var self = this;
self.name = {
value: ko.observable("")
};
self.name.isValid = ko.computed(function () {
//not sure why you are checking length here
return self.name.value().length > 0;
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.