【问题标题】:Auto-load/include for JavaScriptJavaScript 的自动加载/包含
【发布时间】:2011-12-04 16:50:36
【问题描述】:

我有一个名为 common.js 的文件,它包含在我网站的每个页面中,使用 <script />

它会随着我的网站功能的增长而快速增长(我希望;我想)。 :)

举个例子,我有一个 jQuery 事件:

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

    one_of_many_functions($(this));

}

目前,我在common.js 中有那个one_of_many_functions()

JavaScript 是否有可能在调用此类函数时自动加载文件 one_of_many_functions.js,但它不存在?像自动装载机。 :)

我看到的第二个选项是:

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

    include('one_of_many_functions');

    one_of_many_functions($(this));

}

这不是那么自动,但仍然 - 包括想要的文件。

这有可能吗?感谢您的建议! :)

【问题讨论】:

标签: javascript include require autoload autoloader


【解决方案1】:

无法按需直接自动加载外部 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 */
});

【讨论】:

    【解决方案2】:

    当然有可能——但这可能会变得难以管理。为了实现这样的东西,您将不得不维护函数的索引及其相应的源文件。随着您的项目的发展,这可能会因为几个原因而变得麻烦——我脑海中最突出的两个原因是:

    A) 您有额外的责任维护您的索引对象/查找机制,以便您的脚本在找不到您调用的函数时知道在哪里查找。

    B) 这是调试不断增长的项目时可能出错的另一件事。

    我敢肯定,在我写完这篇文章时,其他人会提到这一点,但您最好花时间弄清楚如何将所有代码合并到一个 .js 文件中。这样做的好处是well-documented

    【讨论】:

      【解决方案3】:

      我在一年前创造了一些接近于此的东西。事实上,如果这是该领域的新事物,我已经通过搜索找到了这个线程。您可以在此处查看我创建的内容:https://github.com/thiagomata/CanvasBox/blob/master/src/main/New.js

      我的项目几乎是 100% OOP。所以,我用这个事实来集中我的解决方案。我创建了这个名为“New”的“类”,它习惯于先加载,然后再实例化对象。

      这里是某人使用它的例子:

       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");
      

      在这个版本中,我没有使用一些带有所有 js 文件位置的 json。正如您在此处看到的那样,映射是核心:

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

      但是让这更自动化,使用 gulp 或 grunt 是我正在考虑做的事情,而且没有那么难。

      创建此解决方案是为了在项目中使用。因此,代码可能需要进行一些更改才能用于任何项目。但可能是一个开始。

      希望这会有所帮助。


      正如我之前所说,这仍然是一个工作进展。但我创建了一个更独立的模块,它使用 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 方法中使用:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多