【发布时间】:2014-08-19 04:00:27
【问题描述】:
假设我想构建一个日历应用程序(在 HTML + JS 中),用户可以一次看到一周。
用户应该能够定义事件,例如周一 1:00 - 3:00:
+---------+---------+ +---------+
| Monday | Tuesday | ... | Sunday |
+---------+---------+ +---------+
0:00 | | | | |
+---------+---------+ +---------+
1:00 /////////// | | |
//MyEvent//---------+ +---------+
2:00 /////////// | | |
+---------+---------+ +---------+
...
+---------+ ...
23:00 | | ...
+---------+
我考虑过创建一个模型EventModel 和一个视图EventView,并通过通常的MVC 方法将它们连接起来。 eventView 将作为单独的图层呈现在日历网格的顶部,因此它能够自主保持其大小和位置。EventModel 只有三个属性,startTime、duration和title。
如果用户定义一个跨越午夜的事件,例如周一 23:00 至周二 2:00,事情就会变得更加困难:
+---------+---------+ +---------+
| Monday | Tuesday | ... | Sunday |
+---------+---------+ +---------+
0:00 | /////////// | |
+---------//MyEvent// +---------+
1:00 | /////////// | |
+---------+---------+ +---------+
2:00 | | | | |
+---------+---------+ +---------+
...
+---------+ ...
23:00 //MyEvent// ...
+---------+
现在需要绑定到同一个模型的两个视图。
当然,模型中的所有更改都应反映在视图中。请注意,随着startTime 或duration 属性的更新,单个模型所需的视图数量可能会发生变化(1 到 7)。
换句话说:模型中的更改需要触发该模型的视图实例化/销毁。
我看到了两种可能的方法来实现这一点:
- 使用一些控制器逻辑来动态生成/删除所需数量的视图和模型,并保持模型彼此同步
...这似乎是个坏主意,因为这需要大量的摸索以及额外的模型类别。
或
- 坚持使用一个模型并构建一个类似于一个视图的视图代理,但在内部控制所需的“子视图”数量。
第二种方法对我更有吸引力。我写了一些伪代码来说明它:
ViewProxy.onModelChange(model) {
if (model.hasChanged("startTime") or model.hasChanged("duration"))
this.destroySubviews()
subStartTimes[] = getSubStartTimes(model.startTime, model.duration)
subDurations[] = getSubDurations(model.startTime, model.duration)
subViews[] = this.buildSubviews(subStartTimes, subDurations)
subViews.bind(model, "title")
endif
}
这样做的缺点是子视图不必要地被销毁并在所有模型更新上重新构建(仅title 除外),除非我包含额外的逻辑 - 这不是那么微不足道。另外,这个代理是控制器和视图之间的一些奇怪的东西,这让我感到不舒服。
所以我的问题是:是否有解决此问题的标准方法?如果不是,上述解决方案可能会出现哪些问题?还有其他解决方案吗?
【问题讨论】:
-
该模式称为“MVC”(与您现在似乎正在实施的类似 Rails 的结构相反)。模型应该是以后的应用程序。有点像视图、模板、表示对象和控制器都包含在表示层中。
-
任何使用模板引擎或“非模板引擎”(例如视图中的 php 代码作为视图类的一部分)的任何 MVC 都将支持您从控制器/模型传入参数,然后允许您要使用此信息来构建视图,但是您想使用包含或仅处理与 php 相同的值,而不是从控制器或模型传入它需要的值,一些 MVC 支持您从模型加载视图并将其作为 html 返回,所以如果视图在做应用层的事情,它可以是模型的一部分。
-
我知道我使用 php 作为示例的注释,但这适用于 Java 中的任何内容,例如,您的模板可以是您的标准窗口,也可以是模型/控制器中的窗口组件。