编译显示模块模式

时间:2019-09-23 19:55:53

标签: javascript design-patterns revealing-module-pattern

我正在编写一个使用显示模式模块的应用程序。我正在使用Gulp进行编译,因此可以设置编译顺序。除了某些jQuery外,没有其他框架或库在起作用。

我正在尝试分解文件:

  • 网站的主JS文件
  • 一个用于相应功能的常规设置,
  • 一个用于功能的用户界面
  • 和另一项用于功能数据。

我正在尝试如下命名空间:

myApp
myApp.dashboard
myApp.dashboard.ui
myApp.dashboard.data

问题是名称空间嵌套,因为(例如)我的dashboard.ui.js文件在dashboard.js中被引用

我收到 Uncaught TypeError: Cannot set property 'ui' of undefined尝试访问myApp.dashboard.ui时。

我尝试了所有我能想到的编译顺序。我猜我的模式有问题,但我不确定是什么。这是代码示例。

// app.js

let myApp = (function(){

    const $els = {
        menu: $('#menu')
        // etc.
    };

    const eventHandlers = () => {
        //site-wide click event handlers (for example)
    };

    const utils = {
        // utility functions
    };

    const init = () => {
        // set some site variables, etc.
        eventHandlers();
    };

    return {
        init,
        utils
    };
})(myApp || {});

// dashboard.js

myApp.dashboard = (function (parent){

    // ! need access to the UI
    let ui = parent.dashboard.ui;

    const eventHandlers = () => {
        ...
    };

    const init = () => {
        eventHandlers();
    };

    return {
        init
    };

})(myApp || {});

// dashboard.ui.js

myApp.dashboard.ui = (function (parent){

    // ! need access to the DATA
    let ui = parent.dashboard.data;

    const htmlTemplate = (content) => {
        return `<h1>${content}</h1>`;
    };

    const setValidationFlags = () => {
        ...
    };

    return {
        setValidationFlags
    };

})(myApp || {});

// dashboard.data.js

myApp.dashboard.data = (function (parent){

    const getData = (dataObject) => {
        // do XHR look up
        // call setter, etc.
    };

    const parseForm = () => {
        // collect form data.
    };

    return {
        parseForm
    };

})(myApp || {});

有人可以提供一些有关如何更正我的代码的指导,以便我可以将UI和数据部分嵌套在myApp.dashboard名称空间下,并使这三个部分彼此可访问吗?

如果这种模式不可行,也欢迎提出改进建议。

1 个答案:

答案 0 :(得分:0)

dashboard要求ui要求data,因此您需要以相反的顺序加载它们。并让每个模块设置尚不可用的整个名称空间树:

// data.js
var myApp;
if (!myApp) myApp = {};
if (!myApp.dashboard) myApp.dashboard = {};
myApp.dashboard.data = (function(){
    …
    return { parseForm };
})();

// ui.js
var myApp;
if (!myApp) myApp = {};
if (!myApp.dashboard) myApp.dashboard = {};
myApp.dashboard.ui = (function(){
    // need access to the DATA
    const data = myApp.dashboard.data;
    …
    return {setValidationFlags};
})();

// dashboard.js
var myApp;
if (!myApp) myApp = {};
if (!myApp.dashboard) myApp.dashboard = {};
myApp.dashboard.init = (function(){
    // need access to the UI
    const ui = parent.dashboard.ui;
    …
    return () => {
        eventHandlers();
    };
})();

另一种选择是不使用对IIFE中立即执行的其他模块的引用,而是将它们推迟到init调用之后,此时应该已加载所有模块。