backbone + requirejs:范围问题

时间:2014-07-01 00:13:12

标签: backbone.js requirejs

我有2个观看次数,其中一个是"时间曲目"另一种是创建时间表的表单 第一个附有一个集合。 第二个是时间轨道形式,它定义了一个"创建"在创建新的时间轨迹后,引用第一个重新渲染时间轨迹视图的函数。

时间码代码:

define(['backbone','collections/timetracks', 'views/timetracks/item'], function(Backbone, instanceTimeTracksCollection, TimeTrackView){
    var TimeTrackGrid = Backbone.View.extend({
        //......
    });
    return TimeTrackGrid;

});

表单代码:

define(['backbone', 'collections/timetracks'], function(Backbone, instanceTimeTracksCollection){
    //...............
    //next comes my issue:
    create: function(){
        instanceTimeTracksCollection.create(indexed_array,{
            success: function(model, response) {
                console.info('model created, response = ',response);
                // timeTracksGrid is out of scope, timeTracksGrid would be an instance of timetracks.
                timeTracksGrid.render();
            },
            error: function(error){
                console.info('error=',error);
            },
            wait:true
        });
    }

});

...最后我有app.js定义了两个视图的实例:

requirejs(['backbone','views/timetracks/new','views/timetracks/list'],
    function(Backbone, newTimeTrackForm, timeTracksGrid) {
        var grid = new timeTracksGrid();
        var formView = new newTimeTrackForm();
    });

创建新的时间轨迹后,如何渲染时间轨迹视图?

**************************** 更新 ******** *********

这是我的新版本代码。现在的问题是" this.listenTo(this.collection," add",this.render);"与" this.collection.fetch"重叠。因此,时间跟踪记录会多次呈现。

// timetracks view
define(['backbone','collections/timetracks', 'views/timetracks/item'], function(Backbone, timeTracksCollection, TimeTrackView){
    var TimeTrackGrid = Backbone.View.extend({
            //....
            initialize: function(){
                _.bindAll(this, 'render', 'generateTimeTracks', 'appendTimeTrack');
                this.listenTo(this.collection, "add", this.render);
                this.render();
            }
            render: function(){
                $(this.el).html("<table border='1'></table>");
                this.collection.fetch({
                    success: this.generateTimeTracks
                });
           },
           generateTimeTracks : function(){
                var self = this;
                _(this.collection.models).each(function(item){ 
                    self.appendTimeTrack(item);
                }, this);
           },
           appendTimeTrack: function(item){
                var timeTrackView = new TimeTrackView({
                    model: item
                });
                $('table', this.el).append(timeTrackView.render().el);
           }

    }

其他一些变化:

  • 在app.js而不是按照你的建议做{model:myCollection}我正在做{collection:myCollection}
  • 我的表单代码通过调用this.collection.create
  • 创建一个新模型

再次感谢!

1 个答案:

答案 0 :(得分:1)

另一种解决方案是单独创建视图和集合。

然后在app.js中,您可以将集合传递给两个视图。在TimeTrackGrid的初始化函数中,您应该听取集合上模型的“添加”事件。当这样的事件被触发时,你应该呈现视图。

在表单视图的create方法中,您可以将数据添加到集合中。这样,您的视图就不必了解彼此的任何信息,从而更好地符合模型和视图分离。

因此:

//the grid view
define(['backbone', 'collections/timetracks', 'views/timetracks/item'], function (Backbone, instanceTimeTracksCollection, TimeTrackView) {
    var TimeTrackGrid = Backbone.View.extend({
        initialize: function () {
            //start listening to models being added
            this.listenTo(instanceTimeTracksCollection, "add", this.render)
        },
        render: function () {
            //render your view
            return this;
        }
    });
    return TimeTrackGrid;

});


//and the form view
define(['backbone', 'collections/timetracks'], function (Backbone, instanceTimeTracksCollection) {
    //...............
    //next comes my issue:
    create: function () {
        var data = //get the data from the form
            instanceTimeTracksCollection.add(data) //if you have defined a model on your collection, backbone will automatically instantiate the model
    }
});


//and you app -> notice the reference to the collection definition
requirejs(['backbone','views/timetracks/new','views/timetracks/list', 'collections/timetrackcollection'],
    function(Backbone, newTimeTrackForm, timeTracksGrid) {
        var instanceTimeTracksCollection = new TimeTracksCollection();
        var grid = new timeTracksGrid({model : instanceTimeTracksCollection});
        var formView = new newTimeTrackForm(model : instanceTimeTracksCollection);
    });

EDIT ============================================== ===========

在这里获取配置

requirejs(['backbone','views/timetracks/new','views/timetracks/list'],
    function(Backbone, newTimeTrackForm, timeTracksGrid) {
        var grid = new timeTracksGrid();
        var formView = new newTimeTrackForm();
        var collection = new Collection();
        collection.fetch()
    });

将您的观点更改为:

define(['backbone','collections/timetracks', 'views/timetracks/item'], function(Backbone, timeTracksCollection, TimeTrackView){
    var TimeTrackGrid = Backbone.View.extend({
            //....
            initialize: function(){
                _.bindAll(this, 'render', 'generateTimeTracks', 'appendTimeTrack');
                // maybe backbone does not fire the add event after fetch
                // I believe it does, but I might be mistaken. You will have to look         that up
                this.listenTo(this.collection, "add", this.render);
                this.render();
            }
            //model is passed to the render method by backbone
            render: function(model){
                $(this.el).html("<table border='1'></table>");
                $('table', this.el).append(new TimeTrackView({model : model}).render().el);
           },
           //unused now
           generateTimeTracks : function(){
                var self = this;
                // backbone has underscore build in
                // so use this instead
                this.collection.each(function(item){
                     //do something with item
                }
                _(this.collection.models).each(function(item){ 
                    self.appendTimeTrack(item);
                }, this);
           },
           //unused now
           appendTimeTrack: function(item){
                var timeTrackView = new TimeTrackView({
                    model: item
                });
                $('table', this.el).append(timeTrackView.render().el);
           }

    }