骨干视图事件附加到所有视图

时间:2012-05-19 20:40:07

标签: backbone.js backbone-events backbone-views

我正在我的第一个骨干应用程序,我发现了一个奇怪的事情,试图附加一个事件。

到目前为止,我得到了这段代码:

//View for @girl, EDIT action
GirlEditView = Backbone.View.extend({
    initialize: function(el, attr) {
        this.variables = attr;
        console.log(attr);
        this.render();
    },
    render: function() {
        var template = _.template( $("#girl_edit").html(), this.variables );
        $(this.el).html( template );
        $("#edit_girl").modal('show');
    }
});

//View for @girl
GirlView = Backbone.View.extend({
    initialize: function(el, attr) {
        this.variables = attr;
        this.render();
    },
    render: function() {
        var template = _.template( $("#girl_template").html(), this.variables );
        $(this.el).html( $(this.el).html() + template );
    },
    events: {
        "click p.modify": "modify"
    },
    modify: function() {
        //calls to modify view
        new GirlEditView({el : $("#edit_girl")}, this.variables);
    }
});


//One girl from the list
Girl = Backbone.Model.extend({
    initialize: function() {
        this.view = new GirlView({el : $("#content")}, this.attributes );
    }
});

//all the girls
Girls = Backbone.Collection.extend({
    model: Girl,
});




//do magic!
$(document).ready(function() {

    //Underscore template modification
    _.templateSettings = {
        escape : /\{\[([\s\S]+?)\]\}/g,
        evaluate : /\{\[([\s\S]+?)\]\}/g,
        interpolate : /\{\{([\s\S]+?)\}\}/g
    }

    //get initial data and fill the index
    var list = [];
    $.getJSON('girls.json', function(data) {
        list = [];
        $.each(data, function(key, val) {
            list.push( new Girl(val) );
        });

        var myGirls = new Girls(list);
        console.log( myGirls.models);
    });
});

如你所见。

我正在使用一个集合来存储所有女孩,而数据来自ruby中的REST api。

每个女孩都会创建一个新的模型实例,并在里面附加一个视图实例。

我不知道这是不是一个好习惯,但我想不出更好的方法。

每个视图都会生成一个具有唯一ID的内容。女孩1女孩-2继续。

现在,模板有一个编辑按钮。 我最初的想法是攻击onclick事件并触发编辑视图以进行渲染。

这是按预期工作的。

到目前为止的问题是:

当事件触发时,所有集合(女孩)都会触发编辑视图,而不是“拥有”渲染视图的那个。

我的问题是我做错了什么?

非常感谢

1 个答案:

答案 0 :(得分:4)

所有编辑视图都出现了,因为所有的GirlView都使用相同的el

this.view = new GirlView({el : $("#content")}, this.attributes );

然后你渲染添加更多的HTML:

render: function() {
    var template = _.template( $("#girl_template").html(), this.variables );
    $(this.el).html( $(this.el).html() + template );
}

在视图的el上使用delegate绑定了骨干事件。因此,如果多个视图共享相同的el,您将有多个delegate附加到相同的DOM元素,并且您的事件将是一团糟的内容。

你有点倒退:模特不拥有观点,观看观看模特和收藏品以及回应他们的活动。你会看到这个right in the documentation

  

构造函数/初始化 new View([options])

     

[...]有几个特殊选项,如果通过,将直接附加到视图:modelcollection,[...]

通常,您创建一个集合c,然后通过将该集合交给该集合来创建该视图:

var v = new View({ collection: c })

或者您创建一个模型m,然后创建一个包围该模型的视图:

var v = new View({ model: m })

然后视图绑定到集合或模型上的事件,以便它可以在底层数据更改时更新其显示。该视图还充当Backbone中的控制器,并将用户操作转发给模型或集合。

您的初始化应该更像这样:

$.getJSON('girls.json', function(data) {
    $.each(data, function(key, val) {
        list.push(new Girl(val));
    });

    var myGirls = new Girls(list);
    var v       = new GirlsView({ collection: myGirls });
});

然后GirlsView将遍历该集合并为每个模型创建单独的GirlView

var _this = this;
this.collection.each(function(girl) {
    var v = new GirlView({ model: girl });
    _this.$el.append(v.render().el);
});

然后,GirlView将呈现如下:

// This could go in initialize() if you're not certain that the
// DOM will be ready when the view is created.
template: _.template($('#girl_template').html()),
render: function() {
    this.$el.html(this.template(this.model.toJSON());
    return this;
}

结果是每个模型视图都有自己独特的el来本地化事件。这也使得添加和删除GirlView非常容易,因为所有内容都很好地包含在自己的el中。