2011-04-28 88 views
28

我想玩骨干JS和迄今为止一切似乎是有道理的,工作顺利。骨干JS查看事件不烧?

但是,下面的代码,我的自定义事件似乎并没有被解雇。以下代码中的任何内容都突出了为什么这可能是?我需要在视图中“初始化”任何东西吗?代码/结构上的其他指针也会很酷。以下是我的完整的JS/HTML。

JS

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

var TodoCollection = Backbone.Collection.extend({ 

    model: Todo, 
    url: '/Home/Todos' 

}); 

var AppView = Backbone.View.extend({ 

    // where it should listen, required? 
    el: $(".content"), 

    events: { 
     "keypress #new-todo": "enter" 
    }, 

    initialize: function() { 
     // _.bindAll(this, "render", "createOnEnter"); 
     // this.collection.bind("all", this.render); 
    }, 

    hi: function() { 
     alert('ohai'); 
    }, 

    render: function() { 
     var lis = ''; 
     $.each(this.collection.models, function() { 
      lis += '<li>' + this.get('Text') + '</li>'; 
     }); 
     $('#todo-list').append(lis); 
     return this.el; 
    }, 

    enter: function (e) { 
     alert('hi'); 
    } 

}); 


var TodoController = Backbone.Controller.extend({ 

    routes: { 
     "": "todos" 
    }, 

    initialize: function (options) { }, 

    todos: function() { 
     var todolist = new TodoCollection(); 
     todolist.fetch({ 
      success: function (data) { 
       var appview = new AppView({ collection: data }); 
       appview.render(); 
      } 
     }); 
    } 

}); 

$(function() { 
    window.app = new TodoController(); 
    Backbone.history.start(); 
}); 

HTML

<div id="todoapp"> 
    <div class="content"> 
     <input id="new-todo" placeholder="What needs to be done?" type="text" /> 
     <div id="todos"> 
      <ul id="todo-list"> 
      </ul> 
     </div> 
     <a href="#">say hey</a> 
    </div> 
</div> 

回答

37
el: $(".content") 

试试这个:

var appview = new AppView({ el:$(".content"), collection: data }); 

不能调用一个jQuery那里,因为尚未创建的DOM。您必须在视图以我的示例或初始化加载时执行此操作。

+1

感谢您的回答。我仍然有点困惑,为什么DOM不会在那个时候创建​​。我在底部启动控制器,并将其包装在一个文件准备就绪的通话中。然后我的控制器报道AppView,所以在那个时候不是第一次调用'el'? – aherrick 2011-04-30 09:53:17

+5

var AppView = Backbone.View.extend({})在浏览器读取它时评估。您在文档ready调用中实例化它,但由于_el_不是函数,它将作为扩展的一部分进行评估。 – Julien 2011-05-02 13:20:19

+3

有人可以解释为什么Backbone.js Todo示例在创建AppView时不需要传入参数?他们在todo.js的顶部有这样的注释,“//在DOM准备就绪后,使用'jQuery.ready'加载应用程序:”,但我没有看到他们做了任何事情来确保DOM已经准备就绪。谢谢。 – Quentamia 2011-05-25 15:25:06

16

此外,为了让您的事件发挥作用,您必须将渲染函数中的内容绑定到this.el.事件都与您指定的元素绑定,因此您需要将事件生成元素作为子元素绑定到充当委派者的元素。

+3

我喜欢这个评论两次,但我不能,这正是我的问题,10倍! – 2011-12-12 21:28:38

+0

随着Backbone API的更新,现在也发生了变化。现在有一种方法可以动态设置el,如果使用该方法,那么delegateEvents()会被该函数自动调用。 – 2012-03-01 19:21:16

+0

我不太了解骨干,但我认为这可以通过不指定el属性和在$('。content')渲染函数内部解决。wrap(this.el); – BishopZ 2012-07-13 21:32:55

1

核准的答案有一个缺点。如果您设置{el:$(“。content”)},您就不会变得非常动态。无法在您的DOM内重复使用“.content”元素。只要你在这个视图上调用remove(),$(“。content”)就会消失。

我用另一个参数来传递信息:

{ renderTarget: $("#content") }. 

,并插入我的观点到DOM在渲染的开始:

initialize: function (options) { 
    options = options || {}; 
    this.renderTarget = options.renderTarget || this.renderTarget; 
}, 
render: function() { 
    if (this.renderTarget) { 
     $(this.renderTarget).html(this.el); 
    } 
    ... render stuff into $(this.el) ... 
    return this; 
}