【问题标题】:View Events not firing on created elements?查看事件未在创建的元素上触发?
【发布时间】:2011-12-27 19:43:04
【问题描述】:

尝试创建一个 todo 示例应用程序来搞乱主干。我无法弄清楚为什么任务复选框的点击事件没有触发。这是我的 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 事件不会为这些任务触发。我该如何解决这个问题?

【问题讨论】:

  • 我的回答对你有用还是不清楚?

标签: javascript events backbone.js


【解决方案1】:

这里的问题是,当您创建新视图时,主干事件仅设置为视图元素 (this.el)。但在您的情况下,未使用该元素。所以你的视图中有tagName:li 属性,它让主干创建一个新的li 元素,但你没有使用它。您返回的只是一个从您的模板创建的新列表元素,而不是正在创建的元素主干,您可以通过this.el 访问它

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

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

【讨论】:

    【解决方案2】:

    尝试将使用 .bind() 设置侦听器的行更改为使用 .live()。重要的区别是当你想将监听器绑定到页面加载后创建的元素时,应该使用 .live()。

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

    【讨论】:

    • Backbone 实际上在后台使用delegate
    【解决方案3】:

    您的事件绑定到 .task-complete 类,但复选框上的类是 .task-check

    【讨论】:

    • 改变了(并更新了我的问题),仍然没有解决问题。
    【解决方案4】:

    尝试修改你的渲染函数来调用 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 时,应该可以解决问题。

    【讨论】:

      【解决方案5】:

      @Andreas Kö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,我们必须从模板中删除&lt;li&gt; 标签。

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

      【讨论】:

        猜你喜欢
        • 2019-08-11
        • 2012-04-16
        • 2021-05-14
        • 1970-01-01
        • 1970-01-01
        • 2014-05-01
        • 2012-04-30
        相关资源
        最近更新 更多