Javascript 如何正确使用domReady requireJS插件

Javascript 如何正确使用domReady requireJS插件,javascript,requirejs,domready,Javascript,Requirejs,Domready,在使用domReady之前,这里是我的main.js: require.config({ paths : { loader : 'libs/backbone/loader', jQuery : 'libs/jquery/jquery-module', Underscore : 'libs/underscore/underscore-module', Backbone : 'libs/backbone/backbone-module',

在使用domReady之前,这里是我的main.js:

require.config({
  paths : {
      loader : 'libs/backbone/loader',
      jQuery : 'libs/jquery/jquery-module',
      Underscore : 'libs/underscore/underscore-module',
      Backbone : 'libs/backbone/backbone-module',
      templates : '../Templates'
  }
});

require([ 'app' ], function(app) {
  app.initialize();
});
和app.js:

define([ 'jQuery', 'Underscore', 'Backbone', 'router',
    'services/Initializers/MainFrameInitializer',
    'services/Initializers/FlowsViewsInitializer',
    'services/Initializers/EditModuleInitializer',
    'services/Sandboxes/ModulesNavigationSandbox',
    'services/Sandboxes/ApplicationStateSandbox', 'DataModel/Constants' ],
    function($, _, Backbone, Router, MainFrameInitializer,
        FlowsViewsInitializer, EditModuleInitializer, ModulesNavigationSandbox,
        ApplicationStateSandbox, Constants) {
      var initialize = function() {
        // Pass in our Router module and call it's initialize function
        MainFrameInitializer.initialize();
        FlowsViewsInitializer.initialize();
        EditModuleInitializer.initialize();
        ApplicationStateSandbox.startCheckStatus();
        ModulesNavigationSandbox.navigate(Constants.Modules.Home);
        // Router.initialize();
      };

      return {
        initialize : initialize
      };
    });
在我完成项目之前,一切都很好。我发现,在DOM准备就绪之前脚本就开始运行了,这在优化之前是不正确的。无论如何,我希望使用插件来确保首先加载DOM

但是,显然,我不知道如何正确地做。以下是main.js的新版本:

require.config({
  paths : {
      loader : 'libs/backbone/loader',
      jQuery : 'libs/jquery/jquery-module',
      Underscore : 'libs/underscore/underscore-module',
      Backbone : 'libs/backbone/backbone-module',
      templates : '../Templates'
  }
});

require([ 'domReady', 'app' ], function(domReady, app) {
  domReady(app.initialize);
});
非常整洁而且非常错误,因为在DOM就绪之前,
app
domReady
并行加载

我怎么修理它

谢谢

编辑


我想我已经理解我们的问题了。
app
依赖项的构造函数不应运行任何依赖于DOM的代码。它们应该只返回函数,捕获依赖于DOM的逻辑。应该从
app.initialize
执行该逻辑,该逻辑保证在DOM准备就绪时运行。

也许我遗漏了一些东西,但您是否可以通过执行以下操作来简化您的生活:

require(['jQuery', 'app' ], function(jQuery, app) {
  jQuery(function ($) {
    app.initialize();
  });
});
在您的
main.js

中,如果您遵循以下文档:,您将被邀请在文档头部嵌入require jquery库:

<script data-main="main" src="libs/require-jquery.js"></script>
这意味着您可以将嵌入头部的脚本替换为嵌入文档中任何位置(例如,在文档的最底部)的以下脚本

此后,您可以在任何脚本中使用jquery作为require引用。例如:

  require(["jquery"], function($) { }

通过从domReady回调函数内部请求应用程序,您应该能够同步地请求domReady模块,然后请求应用程序模块

define(['require', 'domReady'], function(require, domReady) {
  domReady(function() {
    require(['app'], function(app) {
      app.initialize();
    });
  });
});

为什么并行加载
domReady
app
是错误的?只有当DOM准备就绪时,才能从
app
调用代码。还是我误解了?可能是我误解了这些东西的工作原理。加载
app
涉及加载所有的app依赖项(其中有很多),然后调用这些依赖项并将结果传递给app factory方法,该方法返回
app
本身。如果我理解正确,
app
的依赖项与
domReady
并行执行,这意味着它们可能会在DOM完全加载之前运行。除非传递给
define()
的工厂函数实际运行代码,否则不会运行任何操作。通常,factory函数只是创建一个对象,其中包含可以在将来某个时候调用的方法(您已经这样做了)。因此,即使对
define()
的调用将运行工厂函数,您也只能在需要时执行真正的应用程序工作。就像您通过将
app.initialize
传递到
domReady
函数所做的那样。我觉得不错。我已经编辑了我的帖子。这就是你的意思吗?我们正在使用jQuery,但你不能直接这样使用它,因为jQuery并没有将自己定义为requireJS意义上的模块。这首先需要一定的准备,我们会做的。另外,请注意,
app
确实依赖于
jQuery
,这是它的第一个依赖项。自iirc 1.7以来,jQuery与AMD兼容。如果依赖于某个以前的版本,则始终可以使用加载程序。依赖于jQuery的应用程序和main不会违反任何规定(jQuery仍然加载一次),但它将允许您不添加其他插件。好的,但此方案仍然要求
app
所依赖的模块的工厂方法不操作DOM,因为
app
依赖项是在jQuery加载的同时解析和调用的。原来的问题仍然存在。但我似乎已经弄明白了这里的症结所在——请看我文章的编辑。没有任何东西要求您不使用jQuery/操纵dom。它只是简单的js。如果您想使用其ready(),可以将jQuery作为依赖项添加到main中。从jQuery 1.7开始,jQuery将自己定义为一个模块,上面的代码将是有效的。在1.7之前,您可以使用require-jquery.js从require-js加载jquery并将其定义为一个模块。
  define( "jquery", [], function () { return jQuery; } );
  require(["jquery"], function($) { }
define(['require', 'domReady'], function(require, domReady) {
  domReady(function() {
    require(['app'], function(app) {
      app.initialize();
    });
  });
});