【问题标题】:RequireJS relative pathsRequireJS 相对路径
【发布时间】:2013-01-10 23:38:10
【问题描述】:

我是 RequireJS 的新手。我在 Knockout.js 中编写了许多自定义绑定,并希望使用模块将它们拆分。

我现在的代码布局是:

/
  default.html
  js
    code.js
    require-config.js 
    lib
      /require.js
      bridge
        bridge.js
        bindings1.js
        bindings2.js
        bindings3.js

我想从 default.html 加载 bridge.js 并将其加载到所有绑定文件中。我尝试使用 require 函数加载 bridge.js 或使用内联 js。

我的 require-config 很简单:

require.config({
    baseUrl: '/'
});

在 bridge.js 中,我在使用相对路径加载文件时遇到问题。我试过了:

require(['./bindings1', './bindings2', './bindings3'], function () {
    console.log('loaded');
});

但这只是使用路径 baseUrl + 'bindings1.js',例如。我在 bridge.js 中尝试了各种迭代。我唯一的成功是如果我写了整个路径:

require(['js/bridge/bindings1', 'js/bridge/bindings2', 'js/bridge/bindings3'], function () {
    console.log('loaded');
});

但这不是我想要的。这似乎是一个非常基本的用例,我想我可能误解了相对路径的工作原理。

谢谢

【问题讨论】:

  • 它与您设置的baseUrl 相关。例如:如果你设置了baseUrl: '/js/lib/bridge',那么你可以使用:require(['bindings1', 'bindings2', 'bindings3']
  • 对,但我还有其他代码要从其他路径加载。我的理解是,如果愿意,您可以使用“./”从与当前 js 文件相同的“目录”加载 JS 文件。 requirejs.org/docs/api.html#modulenotes
  • 对于在 define() 函数调用中可能发生的 require("./relative/name") 调用,请务必要求将“require”作为依赖项,以便解析相对名称正确。您是否也尝试过要求“要求”?
  • @CristiPufu,这行得通。谢谢!为什么必须这样做?如果你输入一个快速的答案,我会接受它。我刚刚注意到的另一个选项是在 require-config 文件中设置路径。

标签: javascript requirejs


【解决方案1】:

相对 ID 是相对于在其中解析 ID 的模块 ID 进行解析的。请参阅AMD specmodule id format 部分。

有两种方法可以将相对依赖 ID 构建到正确的上下文/范围中:

定义调用

定义调用是“模块”的开始/定义。在define() 调用中要求的所有依赖项的范围都在该模块的ID 内/相对于该模块的ID。示例:

// does not matter what the file name is.
define(
    'hand/named/module'
    , ['./child']
    , factoryFunction
)

// inside of 'hand/named/module.js' file.
define(
    ['./child']
    , factoryFunction
)

在上述两种情况下,./child 是根据 define() 调用定义的模块 ID 解析的。两种情况下的模块 id 都是hand/named/module./child 被解析为hand/named/child(显然是+'.js',到时候得到它)

“作用域”要求

您可以通过覆盖将require 调用的范围从全局更改为本地。您实际上不需要覆盖/保留名称require,这是它所做更改的含义。 require 功能成为特定模块的“本地”功能。

// inside 'hand/named/module.js' file
define(
    ['require']
    , function(myLocalRequire){
        require('./child', function(){
            // outcome A
        })
        myLocalRequire('./child', function(){
            // outcome B
        })
    }
)

在结果 A 中,您继续使用“全局”要求 - 附加到父范围的要求。您的 ./child 解析为 baseURL + '/child'

结果 B 是本地范围的,与模块 ID hand/named/module 相关联,因此 ./child 被解析为 hand/named/child

@CristiPufu 建议使用仅在该函数范围内的本地对象覆盖全局 require 变量:

// inside 'hand/named/module.js' file
define(
    ['require']
    , function(require){
        return function(){
            // here we have access only to "local" require,
            // since in the function declaration you decided to
            // override the 'require' variable with new object.
            // All code outside of this function will use global require.
            require('./child', function(){
                // outcome B
            })
        }
    }
)

我的偏好是将所有相关资源放在define 调用中。使它们明确而有趣,因为它们的关系很清楚。

【讨论】:

  • 您的最后一个示例是否引入了并发问题?此依赖项将立即加载,并且不会向请求 module.js 的模块返回任何内容,因为内部 require 是异步的并且不会立即运行。即)从内部要求返回任何东西都没有好处,因为当它执行时,模块早已返回......
  • @computrius 虽然这个例子被简化到骨子里只是为了展示 local require 的使用,但是关于并发问题你通常是正确的。我调整了下面的示例以使并发参数静音,但担心这个答案会使示例有点混乱,因为重点是突出“本地”需求的机制。
  • 这对于 AMD 来说可能是正确的,但我不相信对于 RequireJS 是正确的。请参阅@jrburke(RequireJS 的创建者)的这条推文:twitter.com/jrburke/status/386598717802819584
  • 我已经尝试了好几天了,无论如何,我一直收到一个错误消息“模块名称'../../../src/debugger/test.js'没有尚未加载上下文:_"。
【解决方案2】:

在需要配置中使用“包”。这是您问题的有效答案topic

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

在包内你将能够使用相对路径。

【讨论】:

  • 非常有帮助!谢谢。
猜你喜欢
  • 2012-03-07
  • 1970-01-01
  • 1970-01-01
  • 2014-11-11
  • 1970-01-01
  • 1970-01-01
  • 2014-02-06
  • 2013-05-25
  • 1970-01-01
相关资源
最近更新 更多