JavaScript模块模式及子模块初始化的模式

13

我正在启动一个新项目,回顾我的最佳实践以尽可能避免出现任何问题,并查看我已经形成的不良习惯。

我对使用模块/子模块模式处理JavaScript初始化序列的方法并不是很满意。

假设我的代码最终变成了这样:

FOO.init()
FOO.module1.init()
FOO.module2.init()
FOO.module3.init()
FOO.module4.init()

在全局范围内。

本质上我正在执行以下操作(为了简洁起见省略了错误检查和细节):

var FOO = (function (me) {
    me.init = function () {
        for (var i in me.inits) {
            me.inits[i]();
        }
    }

    return me; 
}(FOO || {}));

var FOO = (function (parent) {
    var me = parent.module1 = parent.module1 || {};

    me.init = function () {
    }

    parent.inits.push(me.init);

    return parent;
}(FOO || {}));

$(document).ready(FOO.init);

用于初始化。

我知道以前读过这方面的内容,但现在无法想出正确的搜索词来找到相关文章。有没有经过深思熟虑和测试的模式可以处理这种情况下的初始化问题呢?

谢谢。

编辑:重新阅读后,我觉得一些背景信息可能有助于回答这个问题。

在我的情况下,每个模块/子模块都在自己的文件中。基础模块定义了站点的基本功能,子模块启用不同的功能。例如,一个子模块可以在搜索框上连接自动完成功能,另一个子模块可以将静态头部图像变成旋转横幅。子模块通过CMS启用/禁用,因此我真的希望摆脱在基础模块内部进行显式调用的方法,以便所有内容都可以由CMS管理。我也知道有特定于CMS的方法可以完成这个任务,但我正在寻找一个通用的JavaScript模式,以提供在使用不同CMS的项目之间的一致性和可重用性。

1个回答

18

就我个人而言,我的编码风格与此不同。这是其中之一。另一个则基本上是模仿 backbone.js 中使用的风格。

var myProgram = (function() {
   var someGlobal, someGlobal2;   

   var subModule1 = (function() {
       ...       

       var init = function() {

       };

       ...

       init();

       return { 
           "someMethod": someMethod,
           ...
       };
   }());

   var OtherSubModule = (function() {
       ...
       var init = function(param) { ... };
       ...
       return { 
           "init": init,
           ...
       };
   }());

   var init = function(param) {
       ...

       OtherSubModule.init({
           "foo": param.foo,
           "bar": param.bar,
           ...
       });
   };


   return { 
       "init": init,
       "somePublic": OtherSubModule.foobar, 
       ...
   }
}());

这取决于我是否需要向其他用户提供公共API,Backbone在这方面做得更好。我更喜欢使用基于init函数进行模块驱动的初始配置和完全基于事件驱动的方式。

[编辑]

考虑到问题已被编辑,我对此有不同的模式。每个文件都在某个对象上定义一个函数,在我的情况下是$.FooBar.plugins

(function() {

    var foo = function() { ... };

    var bar = (function() { ... }());

    myNamespace.plugins["MyPlugin"] = function() {

        ... do stuff
        ... bind to evevnts
    };

}());

然后我们使用了一个类似于以下的启动程序:

(function() {

    var needed = function() {
         // Feature detection
    };

    var load = function() { ... };

    var getOptions = function() {
         // Call something on a page by page basis.
    };

    for (var plugin in pluginList) {
         if (needed(plugin)) {
               load(plugin, function() {
                    // get page specific options
                    var options = getOptions();
                    // run plugin
                    myNameSpace.plugins[plugin](options);
                    // If all have been loaded trigger ready handlers
                    if (pluginCurrentCount == pluginCount) {
                         readyTrigger();
                    }
               });
               pluginCount++;
         }
    }

    // start loading plugins after all have been counted
    load.startLoading();

    var readyTrigger = function() {
         // Run all ready handlers
    }

    // Implement your own DOM ready function to run when all plugins
    // have loaded.
    myNameSpace.ready = function(handler) {
         if (isReady) {
             handler();
         } else {
             readyList.push(handler);
         }

    };
}());

这里虽然有很多间隙和伪代码,但你应该能理解。如果不明白,可以随时提问。

然后在页面上我们有类似这样的东西

<html>
<head>
  <script type="text/javascript">

    var pageSpecific = {
         "pluginName": {
              "cssClass": "foobar",
              "submitOnEnter": false,
              ...
         },
         ...
    };

  </script>
  <script src="bootstrapper.js" />
  ...
</head>
<body>
  ...
</body>
</html>

谢谢。我的实际代码与您的第二个示例更接近,这让我对自己的方法感到更好。您的示例也给了我一些改进的想法。 - mpdonadio

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接