问题描述

我正在将项目从”old” browser-style 模块结构更改为具有 require.js 的”new” browser-or-server-side-javascript 模块结构。

在客户端上,我使用的是异地托管的 jQuery,所以我从他们在 README 的“use priority config” 技术中给出的例子开始:

<title>My Page</title>
<script src="scripts/require.js"></script>
<script>
require({
    baseUrl: 'scripts',
    paths: {
        jquery: 'http://googleajax.admincdn.com/ajax/libs/jquery/1.7.2/jquery.min',
        jqueryui: ...,
        ...
        ... // bunch more paths here
    },
    priority: ['jquery']
}, [ 'main' ]);
</script>

这实际上是正常的。但我想将功能从主要导出到 HTML 网页本身。例如:

<a class="button" href="#" onclick="MyApi.foo();">
    <img src="foo.png" alt="foo" />Click for: <b>Foo!</b>
</a>

在嵌入 AMD 模块模式之前,我会通过在全局空间中创建一个字典对象来从各种文件中公开功能:

// main.js

var MyApi = {};

jQuery(document).ready(function($) {
    // ...unexported code goes here...

    // export function via MyApi
    MyApi.foo = function() {
        alert("Foo!");
    };
});

但是我不知道 require.js 中的正确方法是什么。在<script> 标签中放入更多的 require 语句是否可以,然后命名模块,以便可以在网页内使用?或者这应该总是在 main.js 内动态完成,比如 $('#foobutton').click(...)

最佳解决思路

使用 AMD 的一个好处就是放弃命名空间的需要。试图用 RequireJS 再次创建它们将违背 AMD 推出的模式。

关于使用 main.js,只有当您有一个单一的页面应用程序和所有的代码从一个地方引用时,这只是真的适当。您可以根据需要额外调用电话以要求和加载其他模块。

使用上面的例子,你可以这样做:

foo.js

define(['jquery'], function($) {

    // Some set up
    // code here

    // Return module with methods
    return {
        bar: function() {

        }
    }


});

page.js

require(['foo'], function(foo) {

    // jQuery loaded by foo module so free to use it
    $('.button').on('click', function(e) {
        foo.bar();
        e.preventDefault();
    });

});

然后在您的页面中请求带有 require 的 page.js 文件。

使用上面的例子:

require({
    // config stuff here
}, [ 'page' ]);

或者进一步将其加载到页面中:

<script>
    require(['page']);
</script>

一些额外的点

  • 使用上述模式,page.js 可以轻松地需要许多其他模块来加载其他页面相关的功能。

  • 在将会员附加到全局命名空间之前,您现在可以将该代码拆分成任何页面上可以是 re-used 的单独的模块。所有这些都不依赖于一个全局对象。

  • 使用这种方法将事件附加到你的 DOM 元素最有可能是由 R​​equireJS 提供的 rely on the DOM Ready module

次佳解决思路

您还可以在 javascript 的窗口类中设置引用。

在应用模块 window.MyApi = MyApi; 的底部

<a class="button" href="#" onclick="MyApi.foo();"></a>

第三种解决思路

onclick=""放在您的标记中,感觉很脏 – 与内容混合演示。我建议您添加一个<script> 块,并将 require 放在其中,一旦在回调内部,并在另一个内部 $(document).ready()内,如果需要,请以正常方式连接事件处理程序:$('#node').click(...)。如果你可以这样做一般,它适用于多个页面,然后把它放在一个被缩小,组合和缓存的外部文件中。但是通常这些东西最终是 page-specific,所以页面底部的<script> 标签是避免另外一个外部资源请求的一个很好的解决方案。

第四种思路

另一个解决方案就是使用这样的代码 (当然 requirejs 必须添加到页面中):

<input type="button" onclick="(function() { require('mymodule').do_work() })()"/>

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。