【问题标题】:Relative paths with RequireJS modules/packagesRequireJS 模块/包的相对路径
【发布时间】:2012-03-07 07:40:56
【问题描述】:

我对 RequireJS 还很陌生,但遇到了一些问题。我已经使用 RequireJS 在 Backbone 上编写了一个小框架,我希望它可以在不同的项目中重用。因此,通过一些搜索,我了解到 require 允许包。这似乎是我想要的。我有一个 main.js 文件来启动我的应用程序,它基本上看起来像这样:

require.config({
  packages: ['framework']
});

require(['framework'], function(framework) {
  framework.createDash();
});

然后在与我的 main.js 相同的目录中,我有另一个名为“framework”的目录,其中包含另一个 main.js,如下所示:

define(function(require, exports, module) {
  exports.createDash = function(dash, element) {
    require(['dash/dash.model', 'dash/dash.view'], function(DashModel, DashView) {
      return new DashView({
        model: new DashModel(dash),
        el: element ? element : window
      });
    });
  };
});

在搜索中,我找到了this page,这表明“require”参数的范围应为子模块。但是,当我尝试要求某些东西时,它们仍然与我原来的 main.js 相关。我尝试了很多东西并搜索了几个小时无济于事。有什么方法可以让我的包中的 require/define 调用相对于根目录中的 main.js 包含在内?

【问题讨论】:

    标签: javascript requirejs


    【解决方案1】:

    您需要在 require 配置中将您的子模块定义为包:

    require.config({
      packages: [
        { name: 'packagename',
          location: 'path/to/your/package/root',  // default 'packagename'
          main: 'scriptfileToLoad'                // default 'main' 
        }]
      ... some other stuff ...
    });
    

    要加载您的模块,您只需在要求处使用您的“包名”:

    define(['jquery', 'packagename'], function($, MyPackage) {
      MyPackage.useIt()
    });
    

    在您的包中,您必须使用 ./ 前缀来加载相对于您的子模块的文件:

    define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
      LocalFile.finallyLoaded();
    });
    

    有一个有用的快捷方式:如果你的包名等于你的位置并且你的主文件名为'main.js',那么你可以替换它

      packages: [
        { name: 'packagename',
          location: 'packagename',
          main: 'main'
        }]
    

    到这里:

      packages: ['packagename']
    

    据我所知,您已经尝试定义一个包,但您是否也使用了 ./ 前缀?如果没有此前缀,require 将尝试在其全局根路径中查找文件。如果没有包,./ 将毫无用处,因为相对路径与全局根路径相同。


    干杯

    【讨论】:

    • 这是否仍然允许包单独调用 require.config() 并定义它自己的路径别名列表,只要别名引用的文件以“./”开头?我不想每次使用define() 引用它们时都使用所有文件的完整相对路径。我已经重组了整个项目,但我仍然很好奇。
    • 我知道这个答案有点过时了,但最近,即使没有包,您也可以安全地使用相对路径来要求模块。
    【解决方案2】:

    我找到了问题的答案和解决方案(它们显然不一样)。我想我会在这里发布它以防将来对其他人有所帮助。

    基本上我想要的是在自己的上下文中加载我的框架。我在require 的网站上的configuration sectionexample of how to use it 下找到了上下文选项。最初我尝试这样做:

    var req = require.config({
        baseUrl: 'framework',
        context: 'framework',
    
        paths: {
            jQuery: 'lib/jquery/jquery-1.7.min.js',
            Underscore: 'lib/underscore/underscore.min.js',
            Backbone: 'lib/backbone/backbone.min.js',
            etc...
        }
    });
    
    req(['main'], function() {});
    

    这有两个问题。首先,我的“req”变量是在框架之外定义的,但我希望框架定义它自己的路径。其次,每当框架外的文件需要框架内的文件时,例如,这又需要'jQuery',那么框架实例的上下文中就不需要jQuery(或其他任何东西)的要求,所以它找不到文件。

    我最终做的是将我的框架的 main.js 定义为如下所示:

    var paths = {
        jQuery: 'lib/jquery/jquery-1.7.min.js',
        Underscore: 'lib/underscore/underscore.min.js',
        Backbone: 'lib/backbone/backbone.min.js',
        etc...
    };
    
    define(function() {
        var exports = {};
    
        exports.initialize = function(baseUrl, overridePaths, callback) {
            if(!overridePaths) {
            overridePaths = {};
            }
            if(baseUrl && baseUrl[baseUrl.length - 1] != '/') {
                baseUrl = baseUrl + '/';
            }
    
            var fullpaths = {};
            for(var path in paths) {
                // Don't add baseUrl to anything that looks like a full URL like 'http://...' or anything that begins with a forward slash
                if(paths[path].match(/^(?:.*:\/\/|\/)/)) {
                    fullpaths[path] = paths[path];
                }
                else {
                    fullpaths[path] = baseUrl + paths[path];
                }
            }
    
            var config = {paths: fullpaths};
            for(var pathName in overridePaths) {
                config.paths[pathName] = overridePaths[pathName];
            }
            require.config(config);
    
            // Do anything else you need to do such as defining more functions for exports
    
            if(callback) {
                callback();
            }
        }
    
        return exports;
    });
    

    然后在我的项目的 main.js 文件中,我只是这样做:

    require(['framework/main'], function(framework) {
        // NOTE: This setTimeout() call is used because, for whatever reason, if you make
        //       a 'require' call in here or in the framework without it, it will just hang
        //       and never actually go fetch the files in the browser. There's probably a
        //       better way to handle this, but I don't know what it is.
        setTimeout(function() {
            framework.initialize('framework', null, function() {
                // Do stuff here
            }
        }, 0);
    });
    

    这会将传入框架的 initialize() 方法的任何内容用于“baseURL”,并将其添加到框架定义的不以正斜杠或“anything://”开头的任何路径,除非它们被覆盖路径。这允许使用框架的包覆盖诸如“jQuery”之类的东西。

    【讨论】:

      【解决方案3】:

      这对我有用,在模块名称中添加 "./" 前缀:

      define(function (require, exports, module) {
          exports.createDash = function (dash, element) {
              require([ './dash/dash.model', './dash/dash.view' ], function (DashModel, DashView) {
                  return new DashView({
                      model : new DashModel(dash),
                      el : element ? element : window
                  });
              });
          };
      });
      

      【讨论】:

      • 感谢您的回复。 './' 确实可以加载这两个组件,但我想我没有很好地解释这个问题(主要是因为我认为我在发布时没有完全理解这个问题) .真的我的问题归结为,如何使用 require.config() 定义可以在框架上下文中和没有框架上下文中使用的路径,但仍然包含相同的文件?对于我正在尝试做的事情,可能有更好的解决方案,但至少我现在有一些工作。再次感谢!
      【解决方案4】:

      假设 main.js(或其他包 main)由特定名称调用,一个对我来说非常有效的过程允许直接从 data-main 或外部框架使用带有子模块的包,是使用var baseUrl = require.toUrl('packageName') + '/../' 作为require.config({ paths: { ... } }) 配置文件的前缀。例如:

      var music21Base = require.toUrl('music21') + '/../';
      
      require.config({ paths: {
                                'jquery': music21Base + 'ext/jquery/jquery.2.1.10.min';
                                'subModuleLoader': music21Base + 'src/subModuleLoader';
                               }  });
      

      context: "xxx" 的设置适用于使用 ./modName 调用普通模块,但不适用于我的 paths 参数。

      【讨论】:

      • 这不是很整洁,但它解决了我加载本地小程序的问题。谢谢!
      猜你喜欢
      • 2013-01-10
      • 1970-01-01
      • 2014-02-06
      • 1970-01-01
      • 2016-07-07
      • 2017-08-10
      • 1970-01-01
      • 1970-01-01
      • 2010-09-21
      相关资源
      最近更新 更多