11

给定一个使用 Backbone.js 将 Collection 绑定到 View ( RowsView, 创建一个<ul>) 的页面,该 View ( , 创建一个 ) 为集合中的每个模型创建子视图 ( RowView, 创建<li>),我在为这些模型设置内联编辑时遇到问题集合。

我在视图上创建了一个用文本框替换内容的edit()方法,如果用户在该文本框中按下,我想触发列表中下一个视图的方法。RowViewlitabedit()

我可以得到集合中下一个模型的模型:

// within a RowView 'keydown' event handler
var myIndex = this.model.collection.indexOf(this.model);
var nextModel = this.model.collection.at(myIndex+1);

但问题是,如何找到附加到该模型的视图。父RowsView视图不保留对所有子视图的引用;它的render()方法就是:

this.$el.html(''); // Clear
this.model.each(function (model) {
    this.$el.append(new RowView({ model:model} ).render().el);
}, this);

我是否需要重写它以保留一个单独的指针数组,指向RowView它下面的所有 s?还是有一种聪明的方法可以找到附加了已知模型的视图?

这是整个问题的 jsFiddle:http: //jsfiddle.net/midnightlightning/G4NeJ/

4

2 回答 2

14

在模型中存储对视图的引用并不优雅,但是您可以将视图与带有事件的模型链接起来,这样做:

// within a RowView 'keydown' event handler
var myIndex = this.model.collection.indexOf(this.model);
var nextModel = this.model.collection.at(myIndex+1);
nextModel.trigger('prepareEdit');

在 RowView 中侦听事件 prepareEdit 并在该侦听器中调用 edit(),如下所示:

this.model.on('prepareEdit', this.edit);
于 2012-07-13T15:55:58.463 回答
2

我会说你RowsView应该跟踪它的 component RowViews。个体RowViews 确实是 the 的一部分,RowsView并且视图应该跟踪其部分是有道理的。

所以,你RowsView会有这样的render方法:

render: function() {
    this.child_views = this.collection.map(function(m) {
        var v = new RowView({ model: m });
        this.$el.append(v.render().el);
        return v;
    }, this);
    return this;
}

然后,您只需要一种将 a 转换Tabthis.child_views.


一种方法是使用事件,Backbone 视图Backbone.Events混合在一起,因此视图可以触发自己的事件,而其他事物可以监听这些事件。在你的RowView你可以有这个:

events: {
    'keydown input': 'tab_next'
},
tab_next: function(e) {
    if(e.keyCode != 9)
        return true;
    this.trigger('tab-next', this);
    return false;
}

你的RowsView意愿和你可以有这样的排序:v.on('tab-next', this.edit_next);this.collection.mapedit_next

edit_next: function(v) {
    var i = this.collection.indexOf(v.model) + 1;
    if(i >= this.collection.length)
        i = 0;
    this.child_views[i].enter_edit_mode(); // This method enables the <input>
}

演示:http: //jsfiddle.net/ambiguous/WeCRW/

对此的一个变体是添加RowsViewRowViews 的引用,然后tab_next可以直接调用this.parent_view.edit_next().


另一种选择是将keydown处理程序放在RowsView. 这在 and 之间增加了一些耦合RowViewRowsView但在这种情况下这可能不是一个大问题,但它比事件解决方案有点难看:

var RowsView = Backbone.View.extend({
    //...
    events: {
        'keydown input': 'tab_next'
    },
    render: function() {
        this.child_views = this.collection.map(function(m, i) {
            var v = new RowView({ model: m });
            this.$el.append(v.render().el);
            v.$el.data('model-index', i); // You could look at the siblings instead...
            return v;
        }, this);
        return this;
    },
    tab_next: function(e) {
        if(e.keyCode != 9)
            return true;
        var i = $(e.target).closest('li').data('model-index') + 1;
        if(i >= this.collection.length)
            i = 0;
        this.child_views[i].enter_edit_mode();
        return false;
    }
});

演示:http: //jsfiddle.net/ambiguous/ZnxZv/

于 2012-07-13T20:51:52.633 回答