处理路线时出错:无法读取 Ember.js 中的 属性 'connectOutlet'

Error while processing route: Cannot read property 'connectOutlet' in Ember.js

将 Ember 升级到最新版本后出现以下错误:

Error while processing route: portfolio Cannot read property 'connectOutlet'

每当我从以下位置导航时都会发生错误:

http://localhost:8080/#/portfolio

至:

http://localhost:8080/#/publications

奇怪的是,如果我多次刷新页面,有时它会起作用,有时却不起作用,所以感觉有些文件加载​​得太晚或者可能加载了两次。

aplication.hbs

应用程序视图呈现页眉、页脚和主容器,其中包含应用程序 {{outlet}}

<!-- ... -->
<div class="container" id="maincontainer">
  <div class="maincontainer">
    {{outlet}}
  </div>
</div>
<!-- ... -->

index.hbs

我的索引视图呈现了几个子视图:

<div class="jumbotron fadeInUp animated">
    <div class="row">
        <div id="summary_content">
            {{view view.CvSummaryView}}
        </div>
    </div>
</div>

路线 在我所有的路线中,我只添加了 model() 功能。我不会覆盖 renderTemplate() 或其他任何内容。

define([
    'Ember'
],
    function (Ember) {
        "use strict";

        return Ember.Route.extend({
            model: function()
            {
                var result = {};

                $.ajax({
                    async: false,
                    dataType: "json",
                    url: './website/js/models/portfolio.json',
                    success: function(data){
                        result.portfolio = data;
                    }
                });

                return result;
            }
        });
    }
);

我尝试了以下但没有成功:

renderTemplate: function(){
    this.render({
        outlet: "main",
        into: "application"
    });
}

对于此问题的根本原因,您有什么想法吗?

完整的应用程序源代码可以在 https://github.com/remojansen/remojansen.github.io/tree/master/website/js

找到

更新 1

我一直在阅读 Ember 文档,并将 {{outlet "main"}} 添加到我的应用程序模板中并尝试使用:

renderTemplate: function() {
  this.render('blog', {           // the template to render
    into: 'application',          // the template to render into
    outlet: 'main'                // the name of the outlet in that template
  });
}

我一直在调试 Ember 代码,我实现了这个功能:

function appendView(route, view, options) {
  if (options.into) {
    var parentView = route.router._lookupActiveView(options.into);
    var teardownOutletView = generateOutletTeardown(parentView, options.outlet);
    if (!route.teardownOutletViews) { route.teardownOutletViews = []; }
    replace(route.teardownOutletViews, 0, 0, [teardownOutletView]);
    parentView.connectOutlet(options.outlet, view);
  } else {
    var rootElement = get(route.router, 'namespace.rootElement');
    // tear down view if one is already rendered
    if (route.teardownTopLevelView) {
      route.teardownTopLevelView();
    }
    route.router._connectActiveView(options.name, view);
    route.teardownTopLevelView = generateTopLevelTeardown(view);
    view.appendTo(rootElement);
  }
}

在上面的函数中,在行中:

var parentView = route.router._lookupActiveView(options.into);

变量parentViewnulloptions.into"application"。所以下面的行抛出一个异常:

parentView.connectOutlet(options.outlet, view);

我已经定义了应用程序模板和视图,但没有定义应用程序路径我不知道这是否是问题所在。

谢谢!

调试一段时间后,我注意到 ember router._activeViews 元素并不总是包含 application 视图:

有效

不起作用

我试图分析为什么会这样,因为正如我在问题中所说:

The weird thing is that if I refresh the pages many times sometimes it works and some times it's doesn't so feels like some file is loaded too late or maybe loaded twice.

我几乎可以肯定这与 require.js 的使用和异步加载应用程序组件有关。

解决方案是使用 deferReadiness()advanceReadiness()。这是我所做的,以防将来它可以帮助某人...

app.js

define(['Ember'], function (Ember) {
    "use strict";

    window.app = Ember.Application.create({
      LOG_TRANSITIONS: false, // basic logging of successful transitions
      LOG_TRANSITIONS_INTERNAL: false, // detailed logging of all routing steps
      LOG_VIEW_LOOKUPS: false // detailed logging of view resolution
    });

    // Delay the app's initialization . We will invoke advanceReadiness()
    // when are ready for the app to be initialized
    window.app.deferReadiness();

    return window.app;
});

main.js

require([
    'website/js/app',
    /* routes, views... */
], function (
  app,
  /* routes, views... */
  ){
    "use strict";

    // Configure Routes
    app.Router.map(routes);

    // Set Routes
    app.IndexRoute = indexRoute;
    // ...

    // Set Views
    app.IndexView = indexView;
    // ...

    // We're ready to launch the app!
    app.advanceReadiness();
});