Javascript 模块模式和子模块初始化的模式

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5083409/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-25 15:53:41  来源:igfitidea点击:

Pattern for Javascript Module Pattern and Sub-Module Initialization

javascriptdesign-patterns

提问by mpdonadio

I am starting up a new project and I am reviewing my best-practices to try to prevent any problems, and also to see what bad habits I have gotten into.

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

I am not terribly pleased with how I am handling initialization sequences in Javascript using the module / submodule pattern.

我对使用模块/子模块模式在 Javascript 中处理初始化序列的方式并不十分满意。

Let's say, my code ends up with something like

比方说,我的代码最终是这样的

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

at the global scope.

在全球范围内。

I am essentially doing (error checking and details omittied for brevity):

我基本上是在做(为简洁起见省略了错误检查和细节):

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

for initialization.

用于初始化。

I know I have read up on this before, but I can't come up with the right search terms to find the articles now. Is there a well thought out and tested pattern that handles initialization in sitiation like this?

我知道我之前已经阅读过这方面的内容,但我现在无法想出正确的搜索词来查找这些文章。是否有一个经过深思熟虑和测试的模式可以像这样处理初始化?

Thanks.

谢谢。

EDIT: Upon re-reading this, I think a little context will inform answers.

编辑:重新阅读本文后,我认为一些背景信息会为答案提供信息。

In my case, each module / submodule is in its own file. The base module defines the basic functionality of the site, and sub-modules enable different features. For example, a sub-module may wire up auto-completion on a search box, and another may turn a static header image into a rotating banner. Sub-modules are enabled/disabled by the CMS, so I really do want to divorce explicit calls inside the base module so everything can be managed by the CMS. I also that there are CMS specific ways to accomplish this, but I looking for a generic Javascript pattern for doing this to provide consistency and resuablity between projects that may use a different CMS.

就我而言,每个模块/子模块都在自己的文件中。基本模块定义站点的基本功能,子模块启用不同的功能。例如,一个子模块可能会在搜索框上连接自动完成功能,而另一个子模块可能会将静态标题图像转换为旋转横幅。子模块由 CMS 启用/禁用,所以我真的很想分离基本模块内的显式调用,这样一切都可以由 CMS 管理。我还认为有特定于 CMS 的方法可以完成此操作,但我正在寻找一种通用的 Javascript 模式来执行此操作,以在可能使用不同 CMS 的项目之间提供一致性和可重用性。

回答by Raynos

I personally have a different coding style to that. This is one of them. The other is basically an imitation of the style used in backbone.js

我个人对此有不同的编码风格。这是其中之一。另一种基本上是模仿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, 
       ...
   }
}());

Depends whether I need to supply a public API to other users, which backbone does a lot better. I prefer to make modules driven by an initfunction for initial configuration and for the rest completely event driven.

取决于我是否需要向其他用户提供公共 API,哪个主干做得更好。我更喜欢让模块由一个init函数驱动,用于初始配置,其余的完全由事件驱动。

[Edit]

[编辑]

Given the edited question I have a different pattern for this. Each file defines a function on some object in my case it was $.FooBar.plugins

鉴于编辑过的问题,我对此有不同的模式。在我的例子中,每个文件都在某个对象上定义了一个函数$.FooBar.plugins

(function() {

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

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

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

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

}());

Then we use a boot strapper that was something like this :

然后我们使用一个类似于这样的引导程序:

(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);
         }

    };
}());

That's a lot of gaps and pseudo code but you should get the idea. If it's not obvouis feel to question it.

这是很多空白和伪代码,但你应该明白这个想法。如果这不是显而易见的,那就去质疑它。

Then on the page we have something like this

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

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

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

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