1

虽然 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-ishinvalid事件过滤无效属性:

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+ 模型属性时。此外,这没有考虑必填字段的概念,我通过进行令人不快的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 插件或诸如此类的重量级解决方案。很想看看其他人正在使用什么样的模式。

4

1 回答 1

1

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

于 2013-08-05T18:31:05.793 回答