【问题标题】:backbone + requirejs: scope issue骨干+ requirejs:范围问题
【发布时间】:2014-07-01 00:13:12
【问题描述】:

我有 2 个视图,一个是“timetracks”列表,另一个是创建 timetrack/s 的表单 第一个附有一个集合。 第二个,timetraks 表单,它定义了一个“create”函数,该函数引用第一个函数来在创建新的 timetrack 后重新渲染 timetraks 视图。

时间轨迹代码:

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)“timetrack”是timetrack视图还是模型? 2)您是否需要捕获应该创建或呈现的事件? 3) 你有能力更新视图中的 render() 方法吗?是否可以使用自定义事件?
  • @Evgeniy, 1) “timetracks”是一个视图。 2)对不起,我不明白这个问题 3)我觉得我可以......

标签: backbone.js requirejs


【解决方案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);
    });

编辑=============================================== ===========

在此处获取配置

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);
           }

    }

【讨论】:

  • 感谢您的回答,并为我迟到的回复感到抱歉,我正忙于其他事情,现在我要回到我在 node.js 上的第一步。我听取了您的建议,并分别创建了构造函数的实例。不幸的是,现在我面临“添加”事件的新问题。问题是当时间轨迹视图被渲染时,当发生这种情况时,我正在从服务器获取模型集合,获取是触发“添加”事件的重叠类型。上面是我的代码的新更新。
  • 等等,你会获取整个集合吗?对我来说似乎不合适。查看 mmy 编辑以获取更新。
猜你喜欢
  • 2015-02-26
  • 2012-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-31
相关资源
最近更新 更多