假设我想构建一个日历应用程序(在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
除外),除非我包含额外的逻辑 - 这不是那么简单。此外,这个代理在控制器和视图之间是一些奇怪的事情,这让我感到不舒服。
所以我的问题是:这个问题有一个标准的方法吗?如果没有,上述解决方案可能会出现哪些问题?还有其他解决方案吗?
答案 0 :(得分:1)
您的EventModel
会映射到多个View元素,因为您的模型包含多个子元素(EventDayModel
)。
当然,EventModel
的输入定义可能是title
,startDateTime
,duration
,但模型在概念上由一个或多个EventDayModel
元素组成(每个包含startTime
和duration
)。
因此,不是在EventModel
和EventViewProxy
之间保持一对一的映射(有效控制与每一天相对应的视图元素),为什么不将EventModel
细分为EventDayModel
列表,每个列表都与EventDayView
元素进行一对一映射。
当您更改EventModel
时,会重新计算EventDayModel
列表,并更新相应的EventDayView
元素。
答案 1 :(得分:0)
经过一段时间的搜索后,我发现答案是The Composite Pattern。
因此,我们的想法是将一个事件的所有事件视图片段视为管理多个子视图的单个视图。 至于数据绑定,我想如果没有视图中的一点逻辑,这是不可能的。在我的例子中,我认为视图本身将由较小的MVC层次结构组成(想想 Composite 模式!)。因此,视图中的模型通过简单的数据绑定绑定到子视图,ViewProxy管理底层模型中的更新。
答案 2 :(得分:-2)
您可以模拟重新呈现日历的Google日历结构,而不是销毁和重新创建子视图。
如果使用Angular,则可以绑定范围变量并监视模型属性以更新视图属性。
根据开始和结束时间,可以将每个视图视为“div box”。如果用户删除了该事件,则会从事件列表中删除关联的“div box”和事件对象。
如果事件有更新,那么我们会根据开始和结束时间更新“div box”的坐标。
以下资源是显示Google日历使用的模型结构。