【问题标题】:Dojo loader not loading widget's dependencies used in callbacks?Dojo 加载程序不加载回调中使用的小部件依赖项?
【发布时间】:2012-08-14 16:44:13
【问题描述】:

我在使用 Dojo 的加载程序时遇到了真正的问题。我发现在这里粘贴代码真的很困难,因为这是一个涉及整个应用程序的问题。 我创建了一个名为 LoginForm 的小部件,它的开头如下:

define([
"dojo/_base/declare",
"app/globals",
"app/stores",
"dijit/form/Form",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"dijit/layout/TabContainer",
"dijit/layout/StackContainer",
"dijit/layout/ContentPane",
"dijit/layout/BorderContainer",
"dijit/form/Button",
"app/widgets/ValidationPassword",
"app/widgets/ValidationEmail",
"app/widgets/AlertBar",
"app/widgets/StackFading",
"app/widgets/TabFading",
"dojo/_base/lang",
"app/widgets/BusyButton",
"dojo/_base/json",
"dojo/_base/fx",
"dojo/text!app/widgets/templates/LoginForm.html",

], function(
  declare,
 ...
 , json
 , baseFx
 , templateString
 ){
// Create the "login" pane, based on a normal ContentPane
return declare('app.LoginForm', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], {

  widgetsInTemplate: true,

  templateString:  templateString,

这是一个使用模板的简单小部件,在模板中还有一些子小部件,如此处所述。

现在...我正在尝试在 Ajax 回调中创建一个 Loginform 类型的对象。 但是,加载程序让我失望了。

应用程序的主屏幕如下所示:

define([
"dojo/_base/declare",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"app/widgets/Dashboard",
"app/globals",
"dijit/layout/BorderContainer",
"dijit/layout/StackContainer",
"dijit/layout/TabContainer",
"dijit/layout/ContentPane",
"app/widgets/SearchPage",

 ], function(
 declare
 , _WidgetBase
...
 , SearchPage


){
// Create the "login" pane, based on a normal ContentPane
return declare('AppMainScreen', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], {

...

第三个小部件,仪表板,只有一个按钮:

define([
"dojo/_base/declare",
"app/globals",
"app/defaultSubmit",
"app/stores",
"dijit/form/Form",
"dijit/_WidgetBase",
"dijit/_TemplatedMixin",
"dijit/_WidgetsInTemplateMixin",
"app/widgets/AlertBar",
"app/widgets/BusyButton",
"dojo/_base/json",
"dojo/domReady!",

], function(
  declare
 , g
 , ds
 , stores
 , Form
 , _WidgetBase
 , _TemplatedMixin
 , _WidgetsInTemplateMixin
 , AlertBar
 , BusyButton
 , json
){
// Create the "login" pane, based on a normal ContentPane
return declare('app.Dashboard', [_WidgetBase, _TemplatedMixin, _WidgetsInTemplateMixin ], {


widgetsInTemplate: true,

templateString: '' +
    '<div>' +
    '  <div data-dojo-type="app.AlertBar" data-dojo-attach-point="alertBar"></div>' +
    '  <form data-dojo-type="dijit.form.Form" data-dojo-attach-point="form" method="POST"> ' +
    '    <input type="submit" data-dojo-attach-point="button" data-dojo-type="app.BusyButton" label="Create!" />' +
    '  </form>' +
    '</div>',

该表单的 onSubmit 然后链接到 "app/defaultSubmit", 中的一个函数,内容如下:

define([
'app/globals',
'dijit/registry',
'dojo/query',
'dojo/aspect',
'dojo/_base/lang',  
'dojo/_base/json',
'dijit/Tooltip',
'dijit/Dialog',
'app/widgets/LoginForm',
],function(
g
, registry
, query
, aspect
, lang
, json
, Tooltip
, Dialog
, LoginForm
){

问题是 LoginForm 不起作用,因为 LoginForm 的构造函数不起作用:它说它不能实例化依赖类之一。

现在,如果我将其添加到应用程序的 mainScreen 的 postCreate:

var loginForm = new LoginForm({});

然后,在回调中,LoginForm() 神奇地工作 (!)。

我知道我没有发布所有代码,但是就 AMD 中如何处理依赖项而言,我需要了解什么魔法吗?如何确保在回调中解析模块...?

再见,

佣兵团

【问题讨论】:

  • LoginForm 是否在任何地方的模板中以声明方式使用? (必须在解析此模板之前加载。)
  • 它在另一个页面(登录页面!)上以声明方式使用。当会话到期并且用户需要再次登录时,我计划在回调中以编程方式使用它(我在对话框中创建它)。 “必须在解析此模板之前加载它”是什么意思?我很迷茫......加载机制实际上是如何工作的?如果将声明函数的回调中的变量设置为模块的依赖项...?!?

标签: javascript dojo js-amd


【解决方案1】:

这些评论并不适合 cmets 部分。

我在您的代码中看不到缺陷,但这里有一些需要注意的地方。

关于 AMD 加载程序的说明

不要对加载顺序做出假设。

require(["foo", "bar", function (foo, bar) {
  // use foo and bar
});

foobar 可能首先被加载和调用,因为加载是异步的。唯一可以保证的是它们都会在调用回调函数时被加载。 "foo" 解析为它的 define 函数返回的东西;如果这是undefined,则确保函数返回一个值。

避免循环依赖。

//bar.js
define(["foo"], function (foo) {
  return {};
});

//foo.js
define(["bar"], function (bar) {
  return {};
});

行为已定义(请参阅documentation on modules),但可能难以管理。检查你没有通过传递依赖引入这些(A -> B -> C -> A.)

在尝试parse 模板之前加载传递模板依赖项。

define(["dojo/_base/declare", "dijit/_WidgetBase", "dojo/parser",
        "dijit/form/Button" //need to load this even though it is
                            //not referenced in the function
       ],
        function(declare, _WidgetBase, parser) {

    // pretend this is some custom template format (e.g. DTL)
    var template = "<div data-dojo-type='dijit.form.Button'></div>";

    return declare("foo.Foo", [_WidgetBase, _TemplatedMixin], {
        postCreate: function() {
            this.domNode.innerHTML = template;
            parser.parse(this.domNode);
        }
    });

});

在适当的情况下使用_WidgetsInTemplateMixinstandard template widgets

另外,请务必阅读 1.7 release notes 了解问题和注意事项。

注意:此代码未经测试。


顺便说一句,数组后面的逗号会导致 IE7 出错。

【讨论】:

  • 谢谢!!!最后,我遇到了循环依赖的完美风暴和那个该死的“应用程序”作为全局变量......感谢您的帮助。与此同时,我对代码进行了主要重构......“我猜”这是一件好事。有点。谢谢!
  • 顺便说一句,使用 Explorer 7 的人可以去使用其他软件,因为我什至不会考虑它们。 :D
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-06
  • 2010-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多