2

我有一个非常奇怪的问题。我正在尝试实现“根”视图,它也可以作为一些命名空间结构。codeschool.com 课程第二部分介绍了相同的原则。在这个根视图中,我想捕捉事件“单击按钮”,但这就是问题所在。当我单击按钮时,什么也没发生。

window.App = new (Backbone.View.extend({
  el: $("#app"),
  Collections: {},
  Models: {},
  Views: {},
  Routers: {},
  events: {
    'click button' : function(e) {
      alert("Thank god!");
    }
  },
  render: function(){
    //for test purposes
    console.log($("#app").find("button"));
    console.log(this.$el.find('button'));
  },
  start: function(){
    this.render();
    new App.Routers.PostsRouter();
    Backbone.history.start({pushState: true});
  }
}))();



$(document).ready(function() { App.start() });

HTML 看起来像这样

<body>
    <div id="app">
        <div id="posts"></div>

        <button>Click me</button>
    </div>
</body>

真正奇怪的是console.log 在渲染函数中的输出。两个选择器都是一样的,甚至上下文也是一样的,那么问题出在哪里呢?

console.log($("#app").find("button")); //this returns correct button
console.log(this.$el.find('button')); //this returns 0 occurences (WTF?)

编辑:在稍有改变后el: "#app",仍然是同样的问题。问题是(感谢@nemesv)在加载 DOM 之前实例化此类。但是,在加载 DOM 后无法实例化,因为这样就无法使用该命名空间结构(例如 App.Model.Post = Backbone.Model.extend() )。但是在 codeschool.com 课程中引入了这种“具有命名空间结构的主视图”作为某种良好实践。可以在那里找到解决方案http://jsfiddle.net/BckAe

4

1 回答 1

3

您已将您指定el为 jquery 选择器,但由于您位于对象文字内,因此在加载 DOM 之前它会立即评估。

所以el: $("#app"),不会选择任何东西。

您可以通过使用可以将其初始化el为包含选择器的字符串的主干功能之一来解决此问题。

因此,将您的el声明更改为:

el: "#app"

您的点击事件不会被触发,因为您在加载 DOM 之前实例化了您的视图,因此主干无法为您执行事件委托。

因此,您需要将视图声明和创建分为两个步骤。并且仅在加载 DOM 时实例化您的视图:

var AppView = Backbone.View.extend({
   el: "#app",  
   //...
});

$(document).ready(function() 
{ 
    window.App = new AppView();
    App.start() 
});

演示:JSFiddle

于 2013-02-12T09:30:09.453 回答