【问题标题】:Pattern for Javascript Module Pattern and Sub-Module InitializationJavascript 模块模式和子模块初始化的模式
【发布时间】:2011-07-02 06:56:34
【问题描述】:

我正在启动一个新项目,我正在审查我的最佳实践,以尝试防止出现任何问题,并查看我养成了哪些坏习惯。

我对使用模块/子模块模式在 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 的项目之间提供一致性和可重复性。

【问题讨论】:

    标签: javascript design-patterns


    【解决方案1】:

    我个人对此有不同的编码风格。这是其中之一。另一个基本上是模仿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,哪个主干做得更好。我更喜欢让模块由 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>
    

    【讨论】:

    • 谢谢。我的真实代码有点接近你的第二个例子,这让我对我的方法感觉更好。你的例子也给了我一些改进的想法。
    猜你喜欢
    • 2011-05-05
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 2012-07-22
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多