2

我对骨干相当陌生,想测试一个处理待办事项列表的简单脚本。这是我到目前为止使用的代码:

(function() {

    window.App = {
        Models: {},
        Collections: {},
        Views: {}
    };

    window.template = function(id) {
        return _.template($('#' + id).html());
    }

    App.Models.Task = Backbone.Model.extend({
        validate: function(attributes) {
            if ( !$.trim(attributes.title) ) {
                return 'Invalid title';
            }
        }
    });
    App.Collections.Tasks = Backbone.Collection.extend({
        model: App.Models.Task
    });
    App.Views.Task = Backbone.View.extend({
        tagName: 'li',
        template: template('taskTemplate'),
        initialize: function () {
            this.model.on('change', this.render, this);
            this.model.on('destroy', this.remove, this);
        },
        events: {
            'click .edit': 'editTask',
            'click .delete': 'destroy'
        },
        destroy: function() {
            if (confirm('Are you sure?')) {
                this.model.destroy();
            }
        },
        remove: function() {
            this.$el.remove();
        },
        editTask: function() {
            var newTaskTitle = prompt('New title:', this.model.get('title'));
            this.model.set('title', newTaskTitle, {validate: true});
        },
        render: function() {
            this.$el.html(this.template(this.model.toJSON()));
            return this;
        }
    });
    App.Views.AddTask = Backbone.View.extend({
        el: 'form#addTask',
        initialize: function() {

        },
        events: {
            'submit': 'submit'
        },
        submit: function(event) {
            event.preventDefault();
            var newTaskTitle = $(event.currentTarget).find('input[type=text]').val();
            var task = new App.Models.Task({ title: newTaskTitle });
            this.collection.add(task, {add: true, merge: false, remove: false});
        }
    });
    App.Views.Tasks = Backbone.View.extend({
        tagName: 'ul',
        initialize: function() {
            this.collection.on('add', this.addOne, this);
        },
        render: function() {
            this.collection.each(this.addOne, this);
            return this;
        },
        addOne: function(task) {
            var taskView = new App.Views.Task({ model: task });
            this.$el.append(taskView.render().el);
        }
    });

    var tasks = new App.Collections.Tasks([
        {
            title: 'Go to store',
            priority: 4
        },
        {
            title: 'Go to mall',
            priority: 3
        },
        {
            title: 'Get to work',
            priority: 5
        }
    ]);
    var addTaskView = new App.Views.AddTask({ collection: tasks });
    var tasksView = new App.Views.Tasks({ collection: tasks });
    $('div.tasks').append(tasksView.render().el);
})();

所以模型验证工作正常......唯一的pb是collection.add不验证新添加的模型......是一种强制验证的方法吗?

谢谢, 稀有

4

2 回答 2

2

来自精美手册

证实 model.validate(attributes, options)

[...] 默认情况下validate在之前调用save,但也可以在通过之前set调用{validate:true}

Collection#add不调用save也不set使用validate: true选项调用。如果您想在 期间进行验证add,请这样说:

collection.add(models, { validate: true });

这将validate:true一直下降到Model#set.

快速浏览一个简化的示例可能会有所帮助:

var M = Backbone.Model.extend({
    set: function() {
        console.log('setting...');
        Backbone.Model.prototype.set.apply(this, arguments);
    },
    validate: function() {
        console.log('validating...');
        return 'Never!';
    }
});
var C = Backbone.Collection.extend({
    model: M
});
var c = new C;
c.on('add', function() {
    console.log('Added: ', arguments);
});
c.on('invalid', function() {
    console.log('Error: ', arguments);
});

现在,如果我们这样做(http://jsfiddle.net/ambiguous/7NqPg/):

c.add(
    { where: 'is', pancakes: 'house?' },
    { validate: true }
);

你会看到set用 调用validate: truevalidate将被调用,你会得到一个错误。但如果你这样说(http://jsfiddle.net/ambiguous/7b2mn/):

c.add(
    { where: 'is', pancakes: 'house?' },
    {add: true, merge: false, remove: false} // Your options
);

你会看到没有 被调用,不会setvalidate: true调用validate,并且模型将被添加到集合中。


上述行为是非常隐含的,但没有明确指定,因此您可能不想信任它。Model#initialize确实说:

您可以传入属性的初始值,这将set在模型上。

set明确提及该validate选项。但是,不能保证Collection#add将选项发送到模型构造函数,set或者模型的构造函数将选项发送到set. 因此,如果您想成为真正的偏执狂和面向未来的人,您可以在set您的测试套件中添加一个快速检查这种“选项一直到”的行为;然后,如果它发生变化,你就会知道它并且你可以修复它。

于 2013-06-23T20:03:33.210 回答
1

如果您将选项传递给您的集合添加方法,则不会调用验证方法,并且由于在这种情况下您的参数都设置为默认值,因此不需要传递它们

 this.collection.add(task); 

你可能想看看这个问题。 防止 Backbone.js 模型在首次添加到集合时验证

于 2013-06-23T19:31:14.220 回答