【发布时间】:2015-12-19 10:01:52
【问题描述】:
我在运行一个类的多个实例时遇到了一些问题,同时使用 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 想要互相交谈时,问题就来了。我不能import Layer from './layer' inside element.js 而不必创建一个新实例,也无法访问从应用程序内其他位置创建的图层。
版本 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;
有没有办法在这里两全其美?我已经为应用程序的每个实例考虑了类似 store 的东西,跟踪它自己的图层和元素,但共享它的功能,但我不确定将它放在哪里以及如何传递在应用程序周围引用它。
编辑
澄清一下,因为我在 cmets 中得到了这个问题。实际上,这是一个更大的项目,其中包含许多不同的模块,它们以多种不同的方式相互交互。上面的最小版本只是为了这个问题的目的,但这里有一些附加部分作为 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 个不同的模块彼此之间有很多交互。为了这个问题,我想尽可能地简化一切。 -
我认为您需要将
layer对象(或整个App实例)作为参数传递给addToLayer,否则它不知道在哪里解析名称。如果您不想显式传递它,则需要在构建层时传递引用,并为每个层存储它所属的应用程序。在这两种解决方案中,您都不需要将一个模块导入另一个模块,顺便说一句。 -
@Bergi 我一直在尝试在模块中处理实例,例如为每个实例保留一个 id 并传递它,或者拥有一个包含所有数组的存储模块并让
add(),get()等保留在其他共享模块中。当然有办法让它发挥作用,但我不喜欢的是它再次变得非常复杂,几乎违背了我试图做的事情的目的。我有一种感觉,我不可能是唯一一个遇到这种情况的人,但也许我必须从头开始重新考虑整个结构。
标签: javascript module ecmascript-6