問題描述

我正在將項目從”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 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。