具有共享模块

时间:2015-12-19 10:01:52

标签: javascript module ecmascript-6

我在运行多个类实例时遇到一些问题,同时使用ES6模块来实现更清晰的项目结构。

我将尝试在下面解释我的问题。我的真实项目更大,更复杂,但我以此为例。

版本1

main.js

import App from './app';

let instance1 = new App,
    instance2 = new App;

app.js

import Layer from './layer'
import Element from './element'

class App {
  constructor() {
    this.layer = new Layer;
    this.element = new Element;
  }
  addLayer() {
    this.layer.addLayer();  
  }
  addElement() {
    this.element.addElement();
  }
}

module.exports = App;

layer.js

class Layer {
  constructor() {
    this.layers = [];
  }
  addLayer(name) {
    this.layers.push({
        name: name
    });
  }
}

module.exports = Layer;

element.js

class Element {
  constructor() {
    this.elements = [];
  }
  addElement(name) {
    this.elements.push({
      name: name
    });
  }
}

module.exports = Element;

现在,我获得了instance1instance2的唯一实例,其中包含了自己的图层和元素。当 element.js layer.js 想要彼此交谈时会出现问题。我无法在 element.js import Layer from './layer' 而无需创建新实例,无法访问从其他位置创建的图层。应用

版本2

main.js

import App from './app';

let instance1 = new App,
    instance2 = new App;

app.js

import layer from './layer'
import element from './element'

class App {
  addLayer() {
    layer.addLayer();  
  }
  addElement() {
    element.addElement();
  }
}

module.exports = App;

layer.js

class Layer {
  constructor() {
    this.layers = [];
  }
  addLayer(name) {
    this.layers.push({
      name: name
    });
  }
}

let layer = new Layer;
module.exports = layer;

element.js

class Element {
  constructor() {
    this.elements = [];
  }
  addElement(name) {
    this.elements.push({
      name: name
    });
  }
}

let element = new Element;
module.exports = element;

在这种情况下,我可以从 elements.js 访问图层,反之亦然,但它们也会在应用程序的两个实例之间共享,这不是我想要的。

这开始是一个单独的 app.js ,它包含所有内容并且工作正常,但随着项目的增长,它变得非常难以维护。但下面是我想要实现的一个例子。

app.js

class App {
  constructor() {
    this.layers = [];
    this.elements = [];
  }
  addLayer(name) {
    this.layers.push({
      name: name
    });
  }
  addElement(name) {
    this.elements.push({
      name: name
    });
  }
}

module.exports = App;

有没有办法从这两个世界中获得最佳效果?我已经为应用的每个实例考虑了类似商店的内容,跟踪它自己的图层和元素但分享了它的功能,但我不是确定在哪里放置它以及如何在应用程序周围传递引用。

修改

澄清,因为我在评论中得到了问题。实际上,这是一个更大的项目,有许多不同的模块,它们以很多不同的方式相互交互。上面的最小版本仅用于此问题的目的,但是这里还有一些其他部分作为 layer.js element.js 之间交互的示例。

main.js

instance1.element.get('element1').addToLayer('background');

layer.js

.addLayer(name) {
    this.layers.push({
        name: name,
        elements: [],
        add: (element) => {
            this.elements.push(element);
        }
    });
}

element.js

import layer from './layer';

...

.get(name) {
    let el;
    for(item in this.elements) {
        if(item.name == name) {
            el = item;
            break;
        }
    }
    return el;
}
.addElement(name) {
    this.elements.push({
        name: name,
        addToLayer: (name) => {
            let l;
            for(item in layer.layers) {
               if(item.name == name {
                   l = item;
                   break;
               }
            }
            if(l) l.add(this);
        }
    });
}

版本1 中,layer.layers在此处为空,因为我必须创建它的新实例。在版本2 中,它可以正常工作,但App的所有实例都会共享相同的layer.layers

2 个答案:

答案 0 :(得分:1)

版本1

app.js

SELECT COUNT(*) AS COUNT, DATE(CREATED_AT) AS CREATED_AT
FROM ACCOUNT
WHERE CREATED_AT >= DATE_SUB(CURDATE(), INTERVAL 4 day)
GROUP BY DATE(CREATED_AT)
ORDER BY CREATED_AT ASC;

layer.js

import Layer from './layer'
import Element from './element'

class App {
  constructor() {
    this.layer = new Layer(this);
    this.element = new Element(this);
  }
  addLayer() {
    this.layer.addLayer();  
  }
  addElement() {
    this.element.addElement();
  }
}

module.exports = App;

element.js

class Layer {
  constructor(app) {
    this.App = app;
    this.layers = [];
  }
  addLayer(name) {
    this.layers.push({
        name: name
    });
    this.App.element.addElement(name); // Element method
  }
  foo() {
    console.log('Hey you!!');
  }
}

module.exports = Layer;

另见https://github.com/jonataswalker/es6-sample-project

答案 1 :(得分:0)

在过去的几天里,我一直在解决相同的问题,并提出了一种不需要使用类的方法。

我的完整解决方案是针对需要对具有多个地图的仪表板进行实例化的地图控件。

免责声明;我自己没有提出这个解决方案,而是使用了code mentor的建议。


main.mjs

import App from './app.mjs';

const instance1 = App();

const instance2 = App();

app.mjs

import Layer from './layer.mjs';

import Element from './element.mjs';

export default () => {

  const app = {};

  Layer(app);

  Element(app);

  return app;

}

layer.mjs / element.mjs

export default app => {

  app.layers = [];

  app.addLayer = name => {
    app.layer.push({
      name: name
    })
  }

}

此外,我创建一个lib.mjs文件,该文件与Webpack捆绑在一起并用作源库文件。在此处导入实例构造函数“ App”,并将此函数分配给窗口对象。

Here is a jsfiddle in which I import the bundled library and create two map instances.

lib.mjs

import App from './app.mjs';

window.App = App;