ember.js - Emberjs Controller 初始化

标签 ember.js

我已经使用 emberjs 玩了几天,我认为我了解基础知识。现在我正在尝试构建一个真实世界的应用程序,并且已经遇到了一个奇怪的问题。

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

我试过这个: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

    }

});

但它不起作用,因为第 47 行中的 controllerFor() 方法返回了 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

    }

});

在注入(inject)模型时使用单例 Controller 实例,一切正常。

现在我的问题:

  • 创建新实例的 controllerFor() 是一个错误吗?如果不是,为什么它会这样或者我做错了什么?
  • 我在第二把 fiddle 中使用的方法是否合适,或者是否有更好的方法?

最佳答案

I want to have an application template that uses the 'view' helper to include some other views.

如果您只需要一个没有 Controller 的简单 Ember.View,则 {{view}} 助手是合适的。例如像 Ember.InputField 这样的东西。对于应用程序的页眉和侧边栏,您通常需要一个由 Controller 支持的 View 。在这种情况下,请改用 {{render}} 助手。看看这个blog post了解更多详情。

I also want to have some 'global' models that contain information about the environment (e.g. the logged in users account information etc.) that I want to be able to use in different views.

有道理。存储该信息的正确位置是在 Controller 中。这可能是 ApplicationController 的属性,或者在像 currentUserController 这样的单独 Controller 中。由于 View 应该只访问它自己的 Controller 的属性,因此您可以使用 Controller 的 needs 数组来使其可访问。参见 managing dependencies between controllers

Is the controllerFor() creating a new instance a bug?

不,这不是错误。

If not, why does it behave like this or what am I doing wrong?

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

Is the way I worked around in my second fiddle a proper way to do it, or is there a better way?

绝对不是正确的方法。在这个 fiddle 中,您正在使用一个全局变量来完成 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,因为 ember 会自动生成它们。每个都将绑定(bind)到其 Controller 的单例实例,并且可以通过 controllerFor 从您的路由访问这些 Controller 。

JSFiddle 在这里:http://jsfiddle.net/NQKvy/1/

关于ember.js - Emberjs Controller 初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17412759/

相关文章:

javascript - 路由中的 Ember "Params is not defined"

javascript - 我希望根据当前路线将多个变量切换为 true 或 false

javascript - 如何强制 ember 数据在重新加载时重置记录的所有字段?

ember.js - 如何在 Ember.js 中对模型进行排序?

ember.js - 包括ember-cli的依赖项

jquery - 加载 Ember.View 的内容后初始化 jQuery 插件

javascript - Emberjs Controller 需要的不是更新 View

ember.js - 在 Ember 中设计主导出

ember.js - Ember.get() 和 this.get() 的区别

javascript - 为什么 Ember 将所有内容安装为 devDependencies 而不是正常的依赖项