简体   繁体   English

require.js + backbone.js:如何构造具有初始化函数的模块?

[英]require.js + backbone.js: How to structure modules that have an initialize function?

I have an application with three pages (which are single-page interfaces). 我有一个有三页的应用程序(单页界面)。 The pages have similar but not identical functionality. 页面具有相似但不相同的功能。

So I want to have javascript-modules that provide the common functionality. 所以我想拥有提供常用功能的javascript模块。 Then each page may customize/overwrite parts of the common functionality. 然后,每个页面可以定制/覆盖部分常用功能。

I'm using backbone.js, so what I do is: 我正在使用backbone.js,所以我做的是:

  1. load the files containing the common Models, Views, Collections etc. 加载包含常见模型,视图,集合等的文件。
  2. load app-specific files that customize/overwrite parts of step 1 加载特定于应用程序的文件,用于自定义/覆盖步骤1的部分内容
  3. call an init() function that instanciates all necessary Models/Views/Collections 调用init()函数,该函数实例化所有必需的模型/视图/集合

At the moment I store my modules in a module-container similar to this: https://stackoverflow.com/a/9426071 Each module has an optional init() function that is executed by my main init() function. 目前我将模块存储在类似于这样的模块容器中: https//stackoverflow.com/a/9426071每个模块都有一个可选的init()函数,由我的主init()函数执行。

Example: 例:

  1. I have a file called results.js. 我有一个名为results.js的文件。 It defines the common Model/Collection/View of search-results. 它定义了搜索结果的通用模型/集合/视图。 In its init() function everything is instanciated, but this function is not yet called: 在它的init()函数中,一切都是instanciated,但是这个函数还没有被调用:

     var resultView = new ResultView() 
  2. Then I include myApp.js, and parts of the View are overwritten. 然后我包含myApp.js,并覆盖部分视图。

  3. The main init() function calls results.js init() which instanciates the new View. 主init()函数调用results.js init()来实现新的View。 Everything works nice, smooth and DRY. 一切都很好,流畅和干燥。

Now I want to switch to require.js instead of my own module-container, and wonder how to organize my code. 现在我想切换到require.js而不是我自己的模块容器,并想知道如何组织我的代码。

I could either instanciate all models/views etc. in myApp.js instead of the init() function of each module. 我可以在myApp.js中实例化所有模型/视图等,而不是每个模块的init()函数。 This would mean to have a lot of repetitive code. 这意味着有很多重复的代码。

Or I could stick to each module having its init() function, and call those init() functions in myApp.js. 或者我可以坚持使用其init()函数的每个模块,并在myApp.js中调用那些init()函数。 I don't like this because I would have to explicitly write down my modules three times for each of my three pages: 我不喜欢这个,因为我必须为我的三个页面中的每个页面明确写下我的模块三次:

require(['module1', 'module2', 'module3', ...],
  function(module1, module2, module3, ...) {
    var init = function() {
      module1.init();
      module2.init();
      module3.init();
      ...
    }
    return {init: init};
  }
);

For 10 modules plus a number of libraries this is not nice and DRY. 对于10个模块加上许多库,这是不好的和DRY。 Is there any way to access (loop over) all modules that require.js holds? 有没有办法访问(循环)require.js持有的所有模块?

Or am I missing something, should I structure my code in a different way? 或者我错过了什么,我应该以不同的方式构建我的代码吗?

Any hints/thoughts are welcome, 欢迎任何提示/想法,

Michael 迈克尔

As discussed in the comments above, you can avoid having to explicitly reference the parameters of the function by looping over them using the arguments object inside the function body. 正如上面的注释中所讨论的,您可以通过使用函数体内的arguments对象循环遍历它们来避免显式引用函数的arguments So: 所以:

require(['module1', 'module2', 'module3', ..., 'moduleN'],
  function(module1, module2, module3, ..., moduleN) {
    var init = function() {
        module1.init();
        module2.init();
        module3.init();
        ...
        moduleN.init();
    };
    return {init: init};
});

Becomes: 变为:

require(['module1', 'module2', 'module3', ..., 'moduleN'],
  function() {
    var args = arguments;
    var init = function() {
        var module;
        for (module in args) {
            if (args.hasOwnProperty(module) && typeof module.init === 'function') {
                module.init.call(this);
            }
        }
    };
    return {init: init};
});

I added in a hasOwnProperty() check inside the for in loop because, for a number of reasons, it's good practice . 我在for in循环中添加了一个hasOwnProperty()检查,因为有很多原因,这是一个很好的做法 Also, you'll see the explicit check for init being a function before attempting to call it. 此外,在尝试调用init之前,您将看到init是一个函数的显式检查。

The reason for var args = arguments is so you can reference it from the inner function - otherwise you would be referencing the arguments passed to init() , which is not what you want. var args = arguments的原因是你可以从内部函数引用它 - 否则你将引用传递给init()的参数,这不是你想要的。

As and aside, on an architectural level, I think the project structure you've described works incredibly well - I use it on a lot of very big projects and it's never let me down. 除了建筑层面之外,我认为你所描述的项目结构非常好 - 我在许多非常大的项目中使用它并且它永远不会让我失望。 Require.js is awesome! Require.js太棒了! :) :)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM