2011-10-10 53 views
3

我有一個文件叫common.js它包含在我的網站的每個頁面使用<script />自動加載/包括JavaScript

隨着我的網站功能增長(我希望;我想象)它會快速增長。 :)

讓例子,我有一個jQuery事件:

$('#that').click(function() { 

    one_of_many_functions($(this)); 

} 

就目前而言,我有one_of_many_functions()common.js

當某個函數被調用時,JavaScript會自動加載文件one_of_many_functions.js,但它不存在嗎?像自動裝載機一樣。 :)

我看到的第二個選擇是做這樣的事情:不是這樣自動

$('#that').click(function() { 

    include('one_of_many_functions'); 

    one_of_many_functions($(this)); 

} 

,但仍 - 包含所需文件。

這是可能的嗎?謝謝你的建議! :)

+2

這聽起來像你真的很喜歡[RequireJS](http://requirejs.org/) –

回答

4

不可能根據需要直接自動加載外部JavaScript。但是,可以實施類似於您提到的第二條路線的動態包含機制。

雖然有一些挑戰。當你「包含」一個新的外部腳本時,你將不能立即使用包含的功能,你必須等到腳本加載完成。這意味着你必須在一定程度上對你的代碼進行分割,這意味着你必須對核心中包含的內容和需求中包含的內容做出一些決定。

您需要設置一箇中央對象,用於跟蹤哪些資產已經加載。這裏有一個快速的模型:

var assets = { 
    assets: {}, 
    include: function (asset_name, callback) { 
     if (typeof callback != 'function') 
      callback = function() { return false; }; 

     if (typeof this.assets[asset_name] != 'undefined') 
      return callback(); 


     var html_doc = document.getElementsByTagName('head')[0]; 
     var st = document.createElement('script'); 
     st.setAttribute('language', 'javascript'); 
     st.setAttribute('type', 'text/javascript'); 
     st.setAttribute('src', asset_name); 
     st.onload = function() { assets._script_loaded(asset_name, callback); }; 
     html_doc.appendChild(st); 
    }, 
    _script_loaded: function (asset_name, callback) { 
     this.assets[asset_name] = true; 
     callback(); 
    } 
}; 

assets.inlude('myfile.js', function() { 
    /* do stuff that depends on myfile.js */ 
}); 
0

確定這是可能的 - 但這可能會變得痛苦的管理。爲了實現這樣的事情,你將不得不維護一個函數索引和相應的源文件。隨着項目的增長,這可能會有一些麻煩,原因如下:

A)您有責任維護索引對象/查找機制,以便腳本知道在哪裏看看你正在調用的函數何時無法找到。 B)這是調試成長項目時可能出錯的另一件事。

我確定別人會在我寫完這篇文章的時候提及這一點,但是您的時間可能會更好地理解如何將所有代碼合併到一個.js文件中。這樣做的好處是well-documented

0

我在一年前創造了一些與之相近的東西。事實上,如果這是場上的新事物,我已經通過搜索找到了這個線索。你可以看到我在這裏創建了什麼:https://github.com/thiagomata/CanvasBox/blob/master/src/main/New.js

我的項目幾乎100%OOP。所以,我用這個事實來集中我的解決方案。我創建了這個名爲「New」的「Class」,它用於初次加載和實例化對象。

這裏使用它的人的一個例子:

var objSquare = New.Square(); // Square is loaded and after that instance is created 
    objSquare.x = objBox.width/2; 
    objSquare.y = objBox.height/2; 

var objSomeExample = New.Stuff("some parameters can be sent too"); 

在這個版本中,我不使用一些JSON所有的JS文件位置。映射是鐵桿,你可以在這裏看到:

New.prototype.arrMap = { 
    CanvasBox: "" + window.MAIN_PATH + "CanvasBox", 
    CanvasBoxBehavior: "" + window.MAIN_PATH + "CanvasBoxBehavior", 
    CanvasBoxButton: "" + window.MAIN_PATH + "CanvasBoxButton", 
    // (...) 
}; 

但使這更自動,使用一飲而盡或呼嚕聲的東西我在想什麼做的,它並不難。

該解決方案已創建用於該項目。因此,代碼可能需要一些更改才能用於任何項目。但可能是一個開始。

希望這會有所幫助。


正如我之前所說,這仍然是一個工作進展。但是我創建了一個更獨立的模塊,它使用gulp來保持它的更新。

所有魔法闕在這個鏈接找到: https://github.com/thiagomata/CanvasBox/blob/master/src/coffee/main/Instance.coffee
https://github.com/thiagomata/CanvasBox/blob/master/src/node/scripts.js https://github.com/thiagomata/CanvasBox/blob/master/gulpfile.js

很特別的人,應在Instance.coffee

### 
# Create an instance of the object passing the argument 
### 
instaceObject = (-> 
    ClassElement = (args) -> 
    window[args["0"]].apply this, args["1"] 
    -> 
    ClassElement:: = (window[arguments["0"]]):: 
    objElement = new ClassElement(arguments) 
    return objElement 
)() 

此行的這行讓我加載文件後初始化某個對象的實例。正如在創建方法中使用的那樣:

create:()-> 
    @load() 
    return instaceObject(@packageName, arguments)