2011-10-10 55 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)