【问题标题】:Ember app working intermittently- code modularized with requirejsEmber 应用程序间歇性工作 - 使用 requirejs 模块化代码
【发布时间】:2014-01-14 07:57:02
【问题描述】:

这篇文章有很多细节,所以请多多包涵

我的大部分 Ember.js 开发经验都是预发布版 (0.9.8.1),而且我对路由还很陌生。我花了很多时间来理解它们并创建了一个工作应用程序:

http://mbregistry.info/

问题是,我的代码间歇性地不起作用(在 Chrome 中最明显)。起初,我遇到了 ember 找不到模板的问题。我正在覆盖路线的视图并像这样指定模板:

scripts/users.js

define(['scripts/app','text!scripts/templates/UserIndex.html'],
function (app, templateUserIndex) {
    //route is called app.UserIndexRoute
    app.UserIndexView = Ember.View.extend({
        template: Ember.Handlebars.compile(templateUserIndex),
        Created: function () {
            return app.ParseDate(this.get('controller.model.created')).toLocaleDateString();
        }.property('controller.model.created'),
        MailTo: function () {
            return 'mailto:' + this.get('controller.model.email');
        }.property('controller.model.email')
    });
});

我验证了 requirejs 使用文本插件加载 html...但随后发现 StackOverflow 上的其他人在使用“模板”和路由对象中的视图时遇到问题。因此,我没有与之抗争,而是删除了“模板”行并更新了我的 App 类,以在 ready() 事件中为我的所有视图显式设置模板(因为我知道路由将默认模板名称)

scripts/app.js

define(['jquery',
    'handlebars',
    'ember',
    'text!scripts/templates/Application.html',
    'text!scripts/templates/Loading.html',
    'text!scripts/templates/Index.html',
    'text!scripts/templates/OwnedCarsIndex.html',
    'text!scripts/templates/OwnedCar.html',
    'text!scripts/templates/UserIndex.html'],
function (jQuery, handlebars, ember, templateApplication, templateLoading, templateIndex, templateOwnedCarsIndex, templateOwnedCar, templateUserIndex) {
    App = Ember.Application.create({
        ready: function () {
            Ember.TEMPLATES['application'] = Ember.Handlebars.compile(templateApplication);
            Ember.TEMPLATES['loading'] = Ember.Handlebars.compile(templateLoading);
            Ember.TEMPLATES['index'] = Ember.Handlebars.compile(templateIndex);
            Ember.TEMPLATES['ownedCars/index'] = Ember.Handlebars.compile(templateOwnedCarsIndex);
            Ember.TEMPLATES['ownedCar'] = Ember.Handlebars.compile(templateOwnedCar);
            Ember.TEMPLATES['user/index'] = Ember.Handlebars.compile(templateUserIndex);
        },
        LOG_TRANSITIONS: true,
        LOG_TRANSITIONS_INTERNAL: true,
        LOG_VIEW_LOOKUPS: true,
        LOG_ACTIVE_GENERATION: true
    });

    App.Router.map(function () {
        this.resource('users', function () {
            this.resource('user', { path: ':user_id' }, function () {
                this.resource('ownedCars', { path: 'cars' }, function () {
                    this.resource('ownedCar', { path: ':ownership_id' }, function () {
                        this.resource('expenses');
                    });
                });
            });
        });

        this.resource('cars', function () {
            this.resource('car', { path: ':car_id' });
        });
    });

    return App;
});

这解决了模板间歇性无法加载的问题。但是现在,我又间歇性地遇到了路线问题。我有一个链接到帮助程序,这里是页面遇到此问题时的一些控制台输出:

DEBUG: -------------------------------
DEBUG: Ember      : 1.3.0
DEBUG: Handlebars : 1.1.2
DEBUG: jQuery     : 1.10.2
DEBUG: -------------------------------
Attempting URL transition to / 
generated -> route:application Object {fullName: "route:application"}
generated -> route:index Object {fullName: "route:index"}
Transition #1: Beginning validation for transition to index
Transition #1: application: calling beforeModel hook
Transition #1: application: resolving model
Transition #1: application: calling afterModel hook
Transition #1: application: validation succeeded, proceeding
Transition #1: index: calling beforeModel hook
Transition #1: index: resolving model
Transition #1: index: calling afterModel hook
Transition #1: index: validation succeeded, proceeding
Transition #1: Validation succeeded, finalizing transition;
generated -> controller:application Object {fullName: "controller:application"}
Rendering application with default view <(subclass of Ember.View):ember209> Object {fullName: "view:application"}
generated -> controller:index Object {fullName: "controller:index"}
Rendering index with default view <Ember._MetamorphView:ember225> Object {fullName: "view:index"}
Transitioned into 'index'
Transition #1: TRANSITION COMPLETE.
generated -> route:cars Object {fullName: "route:cars"}
generated -> route:cars.index Object {fullName: "route:cars.index"}
generated -> route:users Object {fullName: "route:users"}
generated -> route:user Object {fullName: "route:user"}
generated -> route:user.index Object {fullName: "route:user.index"}

但是当我尝试单击由链接到帮助程序生成的“编辑配置文件”链接时,我得到了这个:

Attempting transition to user.index
Transition #2: Beginning validation for transition to user.index
Transition #2: application: using context from already-active handler
Transition #2: application: validation succeeded, proceeding
Transition #2: users: calling beforeModel hook
Transition #2: users: resolving model
Transition #2: users: calling afterModel hook
Transition #2: users: validation succeeded, proceeding
Transition #2: user: calling beforeModel hook
Transition #2: user: resolving model 
Assertion failed: You used the dynamic segment user_id in your route user, but App.User did not exist and you did not override your route's `model` hook. 
Transition #2: user.index: transition was aborted

我不确定它为什么尝试访问 App.User,而不是 App.UserRoute(App.UserRoute 具有重载的模型函数,可以正确生成模型)

非常感谢任何帮助:)

更新: 我遇到的一个问题(我什至没有提到)我解决了 - 我需要使用 requirejs 的配置来填充 Ember.js:

require.config({
    paths: {
        'text': 'scripts/references/text',
        'jquery': 'scripts/references/jquery-1.10.2.min',
        'handlebars': 'scripts/references/handlebars-1.1.2',
        'ember': 'scripts/references/ember-1.3.0'
    },
   shim: {
       'ember': {
           deps: ['handlebars', 'jquery'],
           exports: 'Ember'
       }
   }
});

这摆脱了间歇性的“找不到模块 jquery”或“找不到模块把手”(仅在转储缓存时发生)。所描述的主要问题仍然存在。在调试器控制台中,这是我在呈现页面时注意到的唯一区别...

工作页面

Transition #1: TRANSITION COMPLETE.
generated -> route:cars Object {fullName: "route:cars"}
generated -> route:users Object {fullName: "route:users"} 

页面不工作(点击链接时出错)

Transition #1: TRANSITION COMPLETE.
generated -> route:cars Object {fullName: "route:cars"}
generated -> route:cars.index Object {fullName: "route:cars.index"}
generated -> route:users Object {fullName: "route:users"}
generated -> route:user Object {fullName: "route:user"}
generated -> route:user.index Object {fullName: "route:user.index"} 

如果您注意到页面输出无效,Ember 正在为尚未使用的路由生成路由对象...为什么这种情况只是有时会发生?

【问题讨论】:

    标签: ember.js requirejs


    【解决方案1】:

    我不确定为什么您会在期望的时候得到 User 模型而不是 UserRoute,但我可以告诉您 Ember 与 AMD 模块开箱即用时效果不佳。它与 resolver 有关,它负责在请求时找出容器中事物的正确名称。 ember-app-kit project 正在开发与 es6 模块转译器(将 es6 模块转译为 AMD 模块)一起使用的解析器的 new version。您可能会从中寻找灵感,以了解如何覆盖默认解析器以使其与 require.js 一起使用。

    【讨论】:

    • 您发布到解析器的链接太棒了!这绝对是我接下来需要查看的内容:) 将根据任何发现更新此内容
    • 看这个帮助我找到了更多信息。正在发生的事情是链接到帮助器正在呈现,并且大多数时候,它只加载顶级路由(我没有定义;因此它们被生成)。间歇时间,它出于某种原因加载嵌套路由,这很奇怪,除了它生成它们(而不是使用我指定的那些)。当点击发生时,解析器找不到 .model() 方法(因为它使用生成的路由)并且默认为 Ember Data 的 find(),它也找不到模型(因为我没有有一个名为 App.User 的模型)
    【解决方案2】:

    找到了!当我意识到模板没有正确编译并且我尝试了我的问题中显示的解决方法时,这对我来说应该更加明显。

    我的问题的根本原因是,在浏览器加载注册路由的 JavaScript 之前,Ember 在处理链接到帮助程序时(间歇性竞争条件)生成路由。我通过让我的模块返回一个函数然后像构造函数一样使用它来解决这个问题。

    所以 scripts/app.js 的最终代码如下所示:

    define(['jquery',
            'handlebars',
            'ember',
            'scripts/users'],
    function (jQuery, handlebars, ember, usersModule) {
        App = Ember.Application.create({
        });
    
        usersModule = new usersModule;
    
        App.Router.map(function () {
            this.resource('users', function () {
                this.resource('user', { path: ':user_id' }, function () {
                    //..
                }
            }
        }
    
        return App;
    });
    

    现在我的 scripts/users.js 模块如下所示:

    define(['text!scripts/templates/UserIndex.html'],
    function (gravitar, templateUserIndex) {
        return function () {
            App.UserIndexRoute = Ember.Route.extend({
                model: function (param) {
                    return this.modelFor('user');
                }
            });
            App.UserIndexView = Ember.View.extend({
                template: Ember.Handlebars.compile(templateUserIndex),
                Created: function () {
                    return App.ParseDate(this.get('controller.model.created')).toLocaleDateString();
                }.property('controller.model.created'),
                MailTo: function () {
                    return 'mailto:' + this.get('controller.model.email');
                }.property('controller.model.email')
            });
        }
    });
    

    因此,总而言之,require.js 仍然可以达到它的目的(我真的很喜欢它),不过,与我使用的 hack 相比,可能有更好的方法将它与 Ember.js 集成。我的问题是我是个白痴,没想到 Ember.js 在加载所有模块之前处理任何东西(其中一些模块注册了路由)。 我看到的间歇性行为是 Ember 在注册所有路由之前在应用程序视图中处理链接到帮助器。

    ember-app-kit 看起来很有趣,但它似乎通过提供一个使用 Ember.js 的完整框架来解决问题(我还没有准备好)。但绝对感谢亚当的帮助:)

    【讨论】:

    • 想在问这个问题几个月后提供更新,我找到并切换到 Ember CLI。我强烈建议使用它而不是像上面那样尝试任何东西。
    猜你喜欢
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2015-01-24
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 2012-01-11
    • 2014-01-27
    相关资源
    最近更新 更多