骨干不会发生事件

时间:2013-06-10 15:32:30

标签: javascript backbone.js

所以这是我在jsfiddle的应用程序示例:http://jsfiddle.net/GWXpn/1/

问题是点击事件根本没有被触发。我没有在控制台中收到任何JS错误。

首先,我希望显示一个无序列表,其中包含几个项目,每个项目都应该是可点击的。这就是我所做的:

var FooModel = Backbone.Model.extend({});

var ListView = Backbone.View.extend({
        tagName: 'ul', // name of (orphan) root tag in this.el
        initialize: function() {
            _.bindAll(this, 'render'); // every function that uses 'this' as the current object should be in here
        },
        render: function() {
            for (var i = 0; i < 5; i++) {
                var view = new SingleView({
                    model: new FooModel()
                });
                $(this.el).append(view.render().el);
            }
            return this; // for chainable calls, like .render().el
        }
    });

      var SingleView = Backbone.View.extend({
        tagName: 'li', // name of (orphan) root tag in this.el
        initialize: function() {
            _.bindAll(this, 'render', 'click'); // every function that uses 'this' as the current object should be in here
        },
        events: {
            "click": "click"
        },
        click: function(ev) {
            console.log("aaa");
            alert(333);

        },
        render: function() {
            $(this.el).append("aaa");
            return this; // for chainable calls, like .render().el
        }
    });

我想将我的应用分成多个模块(标题,正文,页脚),所以我创建了一个抽象模型并从中扩展了我的模块:

var AbstractModule = Backbone.Model.extend({
    getContent: function () {
        return "TODO";
    },
    render: function () {
        return $('<div></div>').append(this.getContent());
    }
});
var HeaderModule = AbstractModule.extend({
    id: "header-module",
});
var BodyModule = AbstractModule.extend({
    id: "body-module",
    getContent: function () {

        var listView = new ListView();

        return $("<div/>").append($(listView.render().el).clone()).html();
    }
});
var ModuleCollection = Backbone.Collection.extend({
    model: AbstractModule,
});

然后我创建了我的主视图并渲染了所有子视图:

var AppView = Backbone.View.extend({
    el: $('#hello'),
    initialize: function (modules) {
        this.moduleCollection = new ModuleCollection();
        for (var i = 0; i < modules.length; i++) {
            this.moduleCollection.add(new modules[i]);
        }
    },
    render: function () {
        var self = this;
        _(this.moduleCollection.models).each(function (module) { // in case collection is not empty
            $(self.el).append(module.render());
        }, this);
    }
});

var appView = new AppView([HeaderModule, BodyModule]);
appView.render();

任何想法为什么?

1 个答案:

答案 0 :(得分:3)

你在一行中有两个错误:

return $("<div/>").append($(listView.render().el).clone()).html();

首先,除非您明确要求,否则clone不会复制事件:

  

通常,绑定到原始元素的任何事件处理程序都不会复制到克隆。可选的withDataAndEvents参数允许我们更改此行为,而是复制所有事件处理程序,并绑定到元素的新副本。
  [...]
  从jQuery 1.5开始,withDataAndEvents可以选择使用deepWithDataAndEvents进行增强,以复制克隆元素的所有子项的事件和数据。

您正在克隆<ul>,因此您需要将这两个标记设置为true

此外,html会返回一个字符串,并且字符串没有事件,因此您可以将事件杀死事件加倍。

我不明白为什么你要克隆任何东西,你应该返回el并完成它:

    return listView.render().el;

如果你坚持克隆,那么你需要这样的东西:

    return $(listView.render().el).clone(true, true);

但那只是毫无意义的忙碌工作。

BTW,'title''Title'是不同的模型属性,因此您需要说:

console.log(this.model.get("title") + " clicked");

而不是

console.log(this.model.get("Title") + " clicked");

另外,Backbone集合有很多Underscore methods mixed in所以不要直接搞乱集合的models,你现在说的是:

_(this.moduleCollection.models).each(...)

只是说:

this.moduleCollection.each(...)

正如Loamhoof所提到的,0.3.3是古代历史,请升级到Backbone,Underscore和jQuery的新版本。您还应该阅读更改日志,以便使用较新的功能(例如this.$el代替$(this.el),减少_.bindAll次来电,listenTo,...)。< / p>

部分更正的演示(包括更新的库):http://jsfiddle.net/ambiguous/e4Pba/

我也扯掉了alert调用,这是一种可恶的调试技术,如果你遇到意外的无限循环会导致巨大的混乱,console.log更友好。