如何在Backbone子视图中绑定click事件

时间:2012-11-07 11:43:20

标签: javascript events backbone.js

我在Backbone子视图中理解事件绑定时遇到问题。我的观点定义如下:

TenantView = Backbone.View.extend({
  events: {
    "click": "setActive"
  },
  initialize: function() {
    this.parentEl = this.options.parentEl;
    return this.render();
  },
  template: new EJS({
    url: '/scripts/templates/tenant.ejs'
  }),
  render: function() {
    $(this.parentEl).children('ul').append(this.template.render(this.model));
    return this;
  },
  setActive: function(event) {
    return this.model.set('active', true);
  }
});

模板只包含li a。通过这种方式,我的视图上的点击事件不会被捕获,我的方法setActive永远不会被触发。

当我通过像el这样的el: 'li'属性扩展我的视图时,我的(2)个视图中的一个正常运行并触发setActive函数。第二种观点根本没有反应。如果我在视图初始化期间隐藏el属性,则工作视图的el属性指向右侧li,失败的视图el指向第一个可以在页面中找到li

正如人们所看到的,当谈到el属性的含义时,我完全迷失了。

问题是,如何将视图上的点击绑定到这个视图setActive函数?

有人可以开导我吗?

此致 菲利克斯

2 个答案:

答案 0 :(得分:2)

首先,您可以阅读documentationthis。那里给出了el的解释。

由于TenantView具有parentEl属性,我假设它是从某些parent_view呈现的。我会建议一些像下面这样的方法并尝试一下。

var ChildView = Backbone.View.extend({
  tagName : "li", // change it according to your needs

  events : {
    "click": "setActive"
  },

  initialize : function() {
    _.bindAll(this, "setActive");
    // code to initialize child_view
  },

  render : function() {
    // as I'm not familiar with the way you are using template, 
    // I've put simple call to render template, but it should render the
    // content to be kept inside "li" tag
    this.$el.html(this.template()); 

    return this;
  },

  setActive : function(event) {
    // code to be executed in event callback
  }
});


var ParentView = Backbone.View.extend({
  el : "#parent_view_el",

  initialize : function() {
    // parent view initialization code
  },

  render : function() {
    // a place from where ChildView is initialized
    // might be a loop through collection to initialize more than one child views
    // passing individual model to the view

    var child_view = new ChildView();

    this.$("ul").append(child_view.render().$el); // equivalent to this.$el.find("ul")

    return this;
  }
});

希望它有所帮助!!

答案 1 :(得分:0)

通过引入parentEl属性并绕过视图元素的创建,您可以获得一些禁用主干的自然行为。你基本上从不将视图`elz属性连接到任何东西。

如果我的代码正确,TenantView是租户列表中的单个列表项。

TenantView中,您可以执行此操作以利用事件中内置的主干:

render: function() {
    this.setElement(this.template.render(this.model));
    $(this.parentEl).children('ul').append(this.$el);
    return this;
}

setElement函数将使用您template函数的返回值来连接views元素,并为您设置事件。在文档中,建议使用setElement支持仅为el属性分配内容。还有一个漂亮的$el属性,它将包含视图元素的缓存jQuery(或Zepto)对象。

要更多地使用骨干方式,我会考虑这样的事情:

var TenantView = Backbone.View.extend({
    // =========
    // = Setup =
    // =========

    events: {
        "click": "setActive"
    },

    template: new EJS({
        url: '/scripts/templates/tenant.ejs'
    }),

    // =============
    // = Lifecycle =
    // =============

    initialize: function(model, options) {
        this.render();
    },

    render: function() {
        var content = this.template.render(this.model);
        this.$el.html(content);
        return this;
    },

    // ==========
    // = Events =
    // ==========

    setActive: function(event) {
        return this.model.set('active', true);
    }

});


var TenantList = Backbone.View.extend({

    // =========
    // = Setup =
    // =========

    id: "tenantList",
    tagName: "ul",

    // =============
    // = Lifecycle =
    // =============

    initialize: function() {
        this.render();
    },

    render: function() {
        if (this.collection.length > 0) {
            this.renderChildren();
        }
    },

    renderChildren: function() {
        var that = this;

        this.collection.each(function(tenant) {
            that.$el.append(new TenantView(tenant).$el);
        });
    }
});