繁体   English   中英

淘汰赛嵌套对象作用域未定义参考

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM