RequireJS模块/包的相对路径

Jus*_*tin 28 javascript requirejs

我是RequireJS的新手,我遇到了一些问题.我使用RequireJS编写了一个基于Backbone构建的小框架,我希望它可以在不同的项目中重用.所以,通过一些搜索,我了解到需要允许包.这看起来像我在寻找.我有一个main.js文件来启动我的应用程序,基本上是这样的:

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

require(['framework'], function(framework) {
  framework.createDash();
});
Run Code Online (Sandbox Code Playgroud)

然后在与我的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
      });
    });
  };
});
Run Code Online (Sandbox Code Playgroud)

在搜索中我发现这个页面表明'require'参数应该作用于子模块.但是,当我尝试要求它们仍然相对于我原来的main.js. 我已经尝试了很多东西,并且搜索了几个小时无济于事.有没有什么方法可以让我的包中的require/define调用相对于它的root中的main.js包含?

小智 51

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

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

要加载模块,您只需要在要求中使用'packagename':

define(['jquery', 'packagename'], function($, MyPackage) {
  MyPackage.useIt()
});
Run Code Online (Sandbox Code Playgroud)

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

define(['globalDependency', './myLocalFile'], function(Asdf, LocalFile) {
  LocalFile.finallyLoaded();
});
Run Code Online (Sandbox Code Playgroud)

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

  packages: [
    { name: 'packagename',
      location: 'packagename',
      main: 'main'
    }]
Run Code Online (Sandbox Code Playgroud)

对此:

  packages: ['packagename']
Run Code Online (Sandbox Code Playgroud)

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


干杯

  • 这是否仍然允许包对require.config()进行单独的调用,并定义它自己的路径别名列表,只要别名引用的文件以'./'开头?我不想每次使用define()引用它们时都必须使用所有文件的完整相对路径.我已经重组了整个项目,但我仍然很好奇. (3认同)

Jus*_*tin 5

我想出了我的问题的答案和解决方案(显然它们不一样).我想我会在这里发布,以防将来可以帮助其他人.

基本上我想要的是在自己的上下文中加载我的框架.我在require的网站上的配置部分下找到了context选项,以及如何使用它示例.最初我通过做类似的事情来尝试这个:

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() {});
Run Code Online (Sandbox Code Playgroud)

这有两个问题.首先,我的'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;
});
Run Code Online (Sandbox Code Playgroud)

然后在我的项目的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);
});
Run Code Online (Sandbox Code Playgroud)

这需要无论是在传递给该框架的initialize()方法"基本URL",并预置,为这个框架定义了一个不以正斜杠或"什么://"开头的任何路径,除非他们是超越路径.这允许使用框架的包覆盖诸如'jQuery'之类的东西.