我在同时使用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;
现在我获得了
instance1
和instance2
的唯一实例,每个实例都包含自己的图层和元素。当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
。
.addToLayer(name)
的方法,该方法应将元素添加到图层中。一个图层可能看起来像{ name: 'layer1', elements: [] }
,我希望能够访问图层数组,找到正确的图层并将元素添加到其中。但正如我所说,这只是一个更大应用程序的非常简化的示例。实际上,有大约20个不同的模块彼此之间有很多交互。为了这个问题的目的,我希望尽量简化一切。 - Magnus Engdallayer
对象(或整个App
实例)作为参数传递给addToLayer
,否则它不知道在哪里解析名称。如果您不想显式传递它,则需要在构建图层时传递引用,并为每个图层存储所属的应用程序。在这些解决方案中,您都不需要将一个模块导入到另一个模块中。 - Bergiadd()
、get()
等保留在其他共享模块中。当然,有办法让它工作,但我不喜欢的是它又变得非常复杂,几乎打败了我尝试做的事情的目的。我有一种感觉,我可能不是唯一遇到这个问题的人,但也许我需要从头重新思考整个结构。 - Magnus Engdal