Ember app间歇性地工作 - 使用requirejs进行模块化编码

时间:2014-01-14 07:57:03

标签: ember.js requirejs

这篇文章有很多细节,请耐心等待

我的大多数Ember.js开发经验都是预发布(0.9.8.1),而且我对路由还不熟悉。我花了很多时间来理解它们并创建了一个有效的应用程序:

http://mbregistry.info/

问题是,我的代码间歇性地不起作用(在Chrome中很明显)。起初,我遇到了没有找到模板的问题。我正在覆盖路线的视图并指定模板,如下所示:

脚本/ 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()事件中为我的所有视图显式设置模板(因为我知道路由将默认模板名称),而不是与之斗争,

脚本/ 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"}

但是当我尝试点击使用link-to helper生成的“编辑个人资料”链接时,我得到了这个:

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正在为尚未使用的路线生成路线对象...为什么有时只会发生这种情况?

2 个答案:

答案 0 :(得分:1)

我不确定为什么你会得到User模型而不是UserRoute,但是我可以告诉你,Ember与开箱即用的AMD模块不太搭配。它与它的resolver有关,ember-app-kit project负责在请求时找出容器中正确的东西名称。 new version正在使用与es6模块转换器(将es6模块转换为AMD模块)的解析器{{3}}一起工作。您可以从中寻找灵感,了解如何覆盖默认解析器以使其与require.js一起使用。

答案 1 :(得分:1)

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

我的问题的根本原因是,在浏览器加载注册路由的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仍然服务于它的目的(我非常喜欢它),尽管可能有更好的方法将它与Ember.js集成,而不是我使用的黑客。我的问题是,我是一个白痴,并没有想到Ember.js在所有模块加载之前处理任何事情(其中一些模块注册路线)。 我看到的间歇性行为是Ember在注册所有路径之前处理应用程序视图中的链接帮助程序。

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