2013-07-01 253 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