2013-07-01 203 views
3

我正在玩emberjs几天了,并认为我了解基础知识。现在我试图构建一个真实世界的应用程序,并且已经陷入了一个奇怪的问题。Emberjs控制器初始化

我想要一个应用程序模板,使用'视图'助手包括一些其他视图。我还希望有一些包含环境信息的“全局”模型(例如登录用户帐户信息等),我希望能够在不同的视图中使用这些模型。

我尝试这样做:http://jsfiddle.net/UzgMd/7/

<script type="text/x-handlebars" data-template-name="header"> 
    <div>Header {{fullName}}</div> 
</script> 

<script type="text/x-handlebars" data-template-name="sidebar"> 
    <div>Sidebar</div> 
</script> 

<script type="text/x-handlebars" data-template-name="application"> 
    <div>{{view App.HeaderView}}</div> 
    <div>{{view App.SidebarView}}</div> 
</script> 

<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script> 
<script type="text/javascript" src="https://raw.github.com/wycats/handlebars.js/1.0.0-rc.3/dist/handlebars.js"></script> 
<script type="text/javascript" src="https://raw.github.com/emberjs/ember.js/release-builds/ember-1.0.0-rc.2.js"></script> 
<script type="text/javascript" src="https://raw.github.com/MilkyWayJoe/cdnjs/master/ajax/libs/ember-data.js/0.12.00-latest20130328/ember-data-latest.js"></script> 

具有以下JS:

App = Ember.Application.create(); 

App.Store = DS.Store.extend({ 
    revision: 12, 
    adapter: 'DS.FixtureAdapter' 
}); 
App.AccountInfo = DS.Model.extend({ 

    firstName: DS.attr('string'), 
    lastName: DS.attr('string'), 

    fullName: function() { 
     return this.get('firstName') + ' ' + this.get('lastName'); 
    }.property('firstName', 'lastName') 
}); 

App.AccountInfo.FIXTURES = [{ 
    id: 1, 
    firstName: "John", 
    lastName: "Doe" 
}]; 

//App.headerController = Ember.ObjectController.extend({}).create(); // works 
App.HeaderController = Ember.ObjectController.extend({}); // doesnt work 

App.HeaderView = Ember.View.extend({ 
    templateName: 'header', 

    //controller: App.headerController // works 
    controller: App.HeaderController.create() // doesnt work 
}); 
App.SidebarView = Ember.View.extend({ 
    templateName: 'sidebar' 
}); 

App.ApplicationController = Ember.Controller.extend({}); 
App.ApplicationRoute = Ember.Route.extend({ 

    model: function() { 
     return App.AccountInfo.find(1); 
    }, 

    setupController: function(controller, model) { 
     this._super(controller, model); 

     //App.headerController.set('model', model); // works 
     this.controllerFor('header').set('content', model); // doesnt work 

    } 

}); 

,但它不工作,因为controllerFor() - 法线47倍的回报的一个新实例HeaderController而不是已经在第30行中创建的实例。如果我再次调用controllerFor(),则不会创建新实例,但会返回第47行调用创建的实例 - 我发现有点混乱。

但是,如果我不喜欢这样写道:http://jsfiddle.net/UzgMd/8/

App = Ember.Application.create(); 

App.Store = DS.Store.extend({ 
    revision: 12, 
    adapter: 'DS.FixtureAdapter' 
}); 
App.AccountInfo = DS.Model.extend({ 

    firstName: DS.attr('string'), 
    lastName: DS.attr('string'), 

    fullName: function() { 
     return this.get('firstName') + ' ' + this.get('lastName'); 
    }.property('firstName', 'lastName') 
}); 

App.AccountInfo.FIXTURES = [{ 
    id: 1, 
    firstName: "John", 
    lastName: "Doe" 
}]; 

App.headerController = Ember.ObjectController.extend({}).create(); // works 
//App.HeaderController = Ember.ObjectController.extend({}); // doesnt work 

App.HeaderView = Ember.View.extend({ 
    templateName: 'header', 

    controller: App.headerController // works 
    //controller: App.HeaderController.create() // doesnt work 
}); 
App.SidebarView = Ember.View.extend({ 
    templateName: 'sidebar' 
}); 

App.ApplicationController = Ember.Controller.extend({}); 
App.ApplicationRoute = Ember.Route.extend({ 

    model: function() { 
     return App.AccountInfo.find(1); 
    }, 

    setupController: function(controller, model) { 
     this._super(controller, model); 

     App.headerController.set('model', model); // works 
     //this.controllerFor('header').set('content', model); // doesnt work 

    } 

}); 

在我注入模型使用单控制器实例,一切工作正常。

现在我的问题:

  • 是在controllerFor()创建一个新的实例的错误吗?如果没有,为什么它会这样做,或者我做错了什么?
  • 是我在第二把小提琴中合适的方式来做的方法,还是有更好的方法?

回答

4

我想要一个应用程序模板,使用'视图'助手包含一些其他视图。如果你想要的是一个简单的Ember.View没有控制器

{{view}}助手是合适的。例如像Ember.InputField。对于应用程序的标题和边栏,您通常需要一个由控制器支持的视图。在这种情况下,请使用{{render}}帮助器。看看这个blog post了解更多详情。

我也想有一个包含有关环境的信息(例如,登录的用户帐户信息等),我希望能够在不同的视图使用一些“全球性”的模型。

有道理。存储该信息的正确位置在控制器中。这可能是ApplicationController的财产或在像currentUserController这样的单独控制器中。由于视图只能访问自己控制器的属性,因此可以使用使用控制器的needs数组来使其可访问。请参阅managing dependencies between controllers

是否为controllerFor()创建了一个新实例的bug?

不,这不是一个错误。

如果没有,为什么它的行为如此或我做错了什么?

问题是您正在尝试手动创建headerController的实例。一般情况下,如果您在控制器上调用create(),那么就会出现问题。 Ember希望自己管理控制器实例,并将它们注册到容器中,以便稍后可以找到它们。由于您的实例未注册,所以当您调用controllerFor()时,ember会创建一个新实例。

是我在我的第二个小提琴中工作的一种正确方法吗?或者有更好的方法吗?

绝对不是正确的方法。在这个小提琴中,您正在使用一个全局变量来自动完成应该为您做的事。这意味着有很多不必要的代码,并且对象之间存在很多耦合,这使得测试变得很难。如果用{{render}}方法去它会是这个样子:

<script type="text/x-handlebars" id="application"> 
    {{render header}} 
    {{render sidebar}} 
    {{outlet}} 
</script> 
<script type="text/x-handlebars" id="header">HEADER {{content}}<hr/></script> 
<script type="text/x-handlebars" id="sidebar">SIDEBAR {{content}}<hr/></script> 


App = Ember.Application.create({}); 
App.HeaderController = Ember.ObjectController.extend(); 
App.SidebarController = Ember.ObjectController.extend(); 
App.IndexRoute = Ember.Route.extend({ 
    setupController: function() { 
     this.controllerFor('header').set('content', 'hi'); 
     this.controllerFor('sidebar').set('content', 'bye'); 
    } 
}); 

使用{{render}}我们并不需要定义HeaderView或SidebarView因为烬会自动生成它们。每个将被绑定到其控制器的单例实例,并且可以通过controllerFor从您的路由访问这些控制器。

的jsfiddle这里:http://jsfiddle.net/NQKvy/1/

+2

感谢您的时间和详细的解释。这样做并不适合(手动创建控制器实例),但我无法找到任何有关DOS和不该做的事情。现在看来更清晰了,我会给渲染助手一个尝试:)。再次感谢。 – Nic