查看事件未在创建的元素上触发?

时间:2011-12-27 19:43:04

标签: javascript events backbone.js

尝试创建一个todo示例应用程序来搞乱骨干。我无法弄清楚为什么任务复选框的click事件没有触发。这是我的TaskCollection,TaskView和TaskListView的代码:

$(document).ready(function() {

Task = Backbone.Model.extend({});

TaskCollection = Backbone.Collection.extend({
    model: 'Task'
});

TaskView = Backbone.View.extend({
    tagName: "li",
    className: "task",
    template: $("#task-template").html(),
    initialize: function(options) {
        if(options.model) {
            this.model = options.model
        }
        this.model.bind('change',this.render,this);
        this.render();
    },
    events: {
            "click .task-complete" : "toggleComplete"
    },
    render: function(){
        model_data = this.model.toJSON();
        return $(_.template(this.template, model_data));
    },
    toggleComplete: function() {
        //not calling this function
        console.log("toggling task completeness");
    }
});

TaskListView = Backbone.View.extend({
    el: $("#task-list"),
    task_views: [],
    initialize: function(options) {
        task_collection.bind('add',this.addTask,this);
    },
    addTask: function(task){
        task_li = new TaskView({'model' : task});
        this.el.append(task_li.render());
        this.task_views.push(task_li);
    },
});
});

任务模板:

<script type='text/template' id='task-template'>
  <li class="task">
        <input type='checkbox' title='mark complete' class='task-check' />
        <span class='task-name'><%= name %></span>
      </li>
</script>

我似乎无法弄清楚为什么toggleComplete事件不会触发任务。我该如何解决这个问题?

5 个答案:

答案 0 :(得分:2)

这里的问题是,在创建新视图时,骨干事件仅设置为视图元素(this.el)。但在您的情况下,元素不使用。因此,您的视图中包含tagName:li属性,这会让主干创建一个新的li元素,但您不会使用它。您返回的是从模板创建的新列表元素,但不是元素主干创建的,您可以通过this.el

访问

因此,您必须手动将事件添加到模板使用jQuery创建的元素中,或将模板作为innerHtml添加到元素中:

(this.el.html($(_.template(this.template, model_data)))

答案 1 :(得分:0)

尝试使用.bind()更改设置侦听器的行以使用.live()。当您想要将侦听器绑定到将在页面加载后创建的元素时,应使用.live()。

最新版本的jQuery消除了这一点丑陋,并简化了用于设置事件监听器的方法。

答案 2 :(得分:0)

您的活动与.task-complete课程绑定,但您的复选框上的课程为.task-check

答案 3 :(得分:0)

尝试修改渲染函数以调用delegateEvents(),如下所示:

render: function(){
    model_data = this.model.toJSON();
    this.el = $(_.template(this.template, model_data));
    this.delegateEvents();
    return this.el;
},

你最好不要将模板更改为不包含li然后返回this.el而不是替换它,但是如果你想要事件工作,你需要将this.el作为根元素单向或其他; delegateEvents()重新附加事件的东西,所以当你改变this.el应该解决这个问题。

答案 4 :(得分:0)

@AndreasKöberle正确回答。您需要为this.el指定一些内容以使事件有效。

我更改了您的模板和TaskView#render()功能。 此JSFiddle已应用更改。

新渲染功能

render: function(){
    var model_data = this.model.toJSON();
    var rendered_data = _.template(this.template, model_data);
    $(this.el).html(rendered_data);
    return this;
}

建议render()返回此内容。

TaskListView#addTask函数中的一行从this.el.append(task_li.render());更改为this.el.append(task_li.render().el);

模板更改

由于我们在render()函数中使用this.el,因此我们必须从模板中删除<li>标记。

<script type='text/template' id='task-template'>
    <input type='checkbox' title='mark complete' class='task-complete' />
    <span class='task-name'><%= name %></span>
</script>