2017-02-11 57 views
0

我在@Domenic的使用requirejs的簡單例子,從這個答案: simple example for using require.js 我在這裏包括。在我提到文件名之前requirejs如何知道加載所需的js文件?

shirt.js:

define({ 
    color: "black", 
    size : "large" 
}); 

logger.js:

define(function (require) { 
    var shirt = require("./shirt"); 

    return { 
     logTheShirt: function() { 
      console.log("color: " + shirt.color + ", size: " + shirt.size); 
     } 
    }; 
}); 

main.js:

define(function (require) { 
    var shirt = require("./shirt"); 
    var logger = require("./logger"); 

    alert("Shirt color is: " + shirt.color); 
    logger.logTheShirt(); 
}); 

main.html中:

<script data-main="../js/main" src="../js/require.js"></script> 

有一些很奇怪的事情:在哪裏shirt.color在main.js使用, shirt.js和logger.js剛剛被安排要加載,asynchonously點 (我相信), 所以shirt.js還沒有真正被讀過。我認爲加載是異步的原因是,我的印象是同步加載在javascript中已經非常不合法(chrome)(XMLHttpRequest仍然有一個選項是同步的,但如果使用的話,它會在Chrome控制檯Synchronous XMLHttpRequest on the main thread is deprecated because of its detrimental effects to the end user's experience.上發出警告)。

然而,這個小應用程序似乎可靠地工作。 它甚至可以可靠地工作,如果我用指向另一個 側的資源的URL替換"./shirt.js",並且在加載html頁面之前清除我的瀏覽器緩存。

這怎麼可能?

如果我看在Chrome開發者控制檯時機,看來耗時shirt.js負荷 前實際發生的請求它甚至開始功能。 也就是說無論如何,它知道在程序中的任何內容之前加載shirt.js完全可以稱爲「./shirt」。

看來這裏有一些非常偷偷摸摸的魔法。 所以我很想知道:

  1. 在任何要求之前,requirejs怎麼知道加載shirt.js?
  2. 這可以在多大程度上依賴?
  3. 如何修改這個例子來避免依靠魔鬼魔法?
  4. 對於我們這些不信任魔鬼魔法的人,有沒有辦法在使用requirejs時禁用它?

回答

1

在任何要求之前,requirejs怎麼知道加載shirt.js?

這是你的模塊:

define(function (require) { 
    var shirt = require("./shirt"); 
    var logger = require("./logger"); 

    alert("Shirt color is: " + shirt.color); 
    logger.logTheShirt(); 
}); 

define被調用時,RequireJS檢測到它被稱爲無依賴列表。因此,它會掃描您爲require調用實例傳遞的回調,該回調採用一個字符串文字的單個參數,並抓取單個參數,並將這些參數的列表作爲模塊的依賴列表。你的模塊成爲功能上等同於這樣:

define(["require", "./shirt", "./logger"], function (require) { 
    var shirt = require("./shirt"); 
    var logger = require("./logger"); 

    alert("Shirt color is: " + shirt.color); 
    logger.logTheShirt(); 
}); 

所以./shirt./logger加載的回調實際上是調用之前。然後,當執行require("./shirt")require("./logger")時,它們只是在已加載模塊的映射中進行查找。 (而且,正因爲如此,調用require用一個字符串參數可以傳遞給define回調調用時。否則,你會得到可怕的"Module has not been loaded yet for context"錯誤只有工作。)

這種能力被稱爲「CommonJS的糖「,因爲一個require調用使用單個參數,這是一個字符串並返回一個模塊是CommonJS本地支持的。本機AMD require調用將一系列依賴關係作爲第一個參數和一個可選的回調函數,解析後的模塊將傳遞給它們。

這可以在多大程度上依賴?

我已經依賴CommonJS糖百種模塊沒有問題。

此模式的一個限制是如果您嘗試將其他字符串文字傳遞給require。例如,如果你這樣做:

define(function (require) { 
    var shirtName = "./shirt"; 
    var shirt = require(shirtName); 

這將甩開RequireJS。它不會檢測到你的模塊需要./shirt模塊,你會得到我上面提到的錯誤。

如何修改這個例子以避免依賴於偷偷摸摸的魔法?

define(["./shirt", "./logger"], function (shirt, logger) { 
    alert("Shirt color is: " + shirt.color); 
    logger.logTheShirt(); 
}); 

對於我們這些誰不信任偷偷摸摸的魔法,有沒有辦法使用requirejs時禁用它?

沒有可以用來阻止RequireJS支持CommonJS糖的標誌。如果你想避免在你自己的代碼中依賴它,你可以編寫你的模塊,就像我在前面的代碼片段中顯示的那樣:調用define,並將依賴列表作爲第一個參數,並獲取模塊作爲回調的參數。

這就是說,我認爲沒有理由這樣做。我已經使用了RequireJS多年,如果有的話我一直在將代碼使用define和一系列依賴關係編碼到依賴於CommonJS糖的代碼中。我發現後者更適合各種開發工具。

相關問題