在Backbone Model / View上处理更复杂的验证逻辑(必填字段等)的最佳方法是什么?

时间:2013-08-05 15:24:42

标签: javascript backbone.js marionette backbone-events

虽然Backbone在模型上的内置validate()方法对于非常简单的情况非常有效,但在处理更复杂的验证逻辑(例如必需字段)时,它很快就会崩溃。在模型上,这是我通常如何处理属性的验证:

validate: function (attrs) {
    var invalid = [],
        dateRegex = /^(\d{2})\/(\d{2})\/(\d{4})$/,
        timeRegex = /^(\d{2}):(\d{2})$/,
        isoDateTimeRegex = /^(\d{4})-(\d{1,2})-(\d{1,2})T(\d{2}):(\d{2}):(\d{2})$/;

    if (_.has(attrs, "chosenScheduleDate") && !dateRegex.test(attrs.chosenScheduleDate)) {
        invalid.push("chosenScheduleDate");
    }

    // ...some more validation rules

    if (invalid.length > 0) {
        return invalid;
    }
},

然后,在视图中,使用new-ish invalid事件过滤无效的属性:

modelEvents: {
    "invalid": "invalidateAttributes"
},

// ...other code

invalidateAttributes: function (model, error) {
    if (_.contains(error, "chosenScheduleDate")) {
        this.unsetModelAttributes("chosenScheduleDate", "chosenScheduleOpenTime", "scheduleOpenTime");

        this.statusNotification.show.call(this, localizedText.displayText.theSelectedDateIsInvalid, "error");

        this.ui.chosenScheduleDateInput.addClass("text-input--error");
    }
},

这可能会导致invalidateAttributes方法很长,特别是如果我正在验证6个以上的Model属性。此外,这没有考虑必要字段的概念,我通过做不愉快的has()检查来处理:

if (this.model.has("scheduleOpenTime")) {
    $.when(this.parent.saveAppointment.call(this))
        .done(function () {
            // set a new attribute on the model that represents the successfully-persisted datetime value
            that.model.set("savedScheduleOpenTime", that.model.get("scheduleOpenTime"));

            that.renderAppointmentForm();
        });
}

然后在尝试集合期间它们无效时必须具有unset()属性,实际上只允许在任何给定时间在模型上存在有效属性。

是否有更好,更优雅的方式来处理Backbone模型上更复杂的验证,包括必填字段?真的更喜欢简单的方法,不使用像Backbone.Validation插件或诸如此类的重量级解决方案。很想看看其他人正在使用什么样的模式。

1 个答案:

答案 0 :(得分:1)

Addy Osmani的Backbone Fundamentals一书有关于模型属性验证的 a great section 。使用 Backbone.Validation plugin 可能是我的第一个建议,因为它很好地处理了必填字段,但您明确提到要避免这种情况。 Addy对该主题的讨论涉及一些替代方案,包括 Backbone.validateAll 插件,或专注于验证表单而非模型。