在Mvc4和Knockout中嵌套多个Views \ ViewModels

我正在开发一个Mvc4 SPA项目,我需要能够将多个视图嵌套在一起。 视图和视图模型使用Durandal进行关联。

在Mvc3中,我以前通过在视图中的局部视图内使用局部视图并将参数传递给局部视图来完成此操作。 这样做,我可以在一对多关系上有多个部分,而这些关系又有多个部分显示全部链接回父视图的一对多关系。

先前在Mvc3 =中使用的示例=

Public class ParentsController
{
public ActionResult Parent(int id)
{
    Parent parent = Db.Parents.Find(id);
    ViewBag.ParentId = parent.Id;
    return View(parent)
}

public PartialViewResult Child(int id)
{
    Child childs = Db.Childs.Where(w => w.ParentId = id);
    return PartialView("ChildPartial", childs.ToList());
}

public PartialViewResult GrandChild(int id)
{
    GrandChild grandChilds = Db.GrandChilds.Where(w => w.ChildId = id);
    return PartialView("GrandChildPartial", grandChilds.ToList());
}
}

和意见类似

Parent.cshtml
@{
    ViewBag.Title = "Parent";
}
@Html.DisplayFor(Model.ParentName)
@{Html.RenderAction("ChildPartial", new { id = ViewBag.ParentId});}


ChildPartial.cshtml
@{
    ViewBag.Title = "Children";
}
{ foreach (var child in childs)
{
@{Html.DisplayFor(child.ChildsName)}
@{Html.RenderAction("GrandChildPartial", new { id = ViewBag.ChildId});}
}}


GrandChildPartial.cshtml
@{
    ViewBag.Title = "Grand Children";
}
{ foreach (var grandChild in GrandChilds)
{
@{Html.DisplayFor(grandChild.GrandChildsName)}
}}

再次,以上是我过去使用过的模式的一个简短例子,不需要帮助。

我可以使用Breeze加载Children并在父视图模型中显示相对容易的孩子,但是当我进入大孩子时,感觉就像我正在进入“意大利面条”代码并从一个视图模型中加载太多。 我认为正确的做法是为父母,孩子和孙子创建一个视图模型,将它们分离出来并使它们可重用。

我的问题是,父视图模型应该加载孩子的视图模型,然后让孩子的视图模型加载孩子的视图,或者应该有一个视图从单独的父对象到子对象组合并级联。 也就是说应该在一个视图中分别加载3个视图模型,还是应该有一个专门的父视图模型,它调用所有三个视图模型并加载它们或多或少相互独立? 我在这里寻找最佳实践,因为SPA理念对我而言是比较新的。


在这里宣布一个最佳实践还为时尚早...特别是当您的应用程序的实际工作流程和性能特征未知时(可能此时不可知)。

一般来说,我们认为每个虚拟机加载所需内容会更好,而不是依赖主虚拟机来提供下级虚拟机。 这里的本能就是你把它分解成单独的虚拟机,这样他们可以执行自己的责任......所以让他们这样做。 主人成为其子虚拟机的协调者,尽可能地保持其实施细节。

我们打算在下个月发布一个名为“ TempHire ”的新样本,植根于“Hot Towel(ette)”,以便提供一些指导。 时机可能不适合你。 但是你可以在GitHub上找到代码),并且我会总结(并简化)与样本相关的样本特征:

  • 主虚拟机与根实体(在你的情况下,一个父)相关联。

  • 主虚拟机接收专用于该根实体的工作流并使用根实体的标识标记的“datacontext”(工作单元[UoW])。

  • “工作单元管理器”通过根实体ID创建和跟踪UoW。 如果您要求为Parent-1申请UoW,它会为您提供正在追踪的一个或为您创建一个新的。

  • 这使得子虚拟机很容易以相互分离的方式与主服务器和彼此共享数据上下文。 主人不必通过嵌套的虚拟机链传递UoW。 相反,每个虚拟机都注入“工作单元管理器”,并可以通过家长ID向“工作单元管理器”请求一个UoW; 它会得到“其他人正在使用”的UoW。

  • 现在任何虚拟机都可以通过向UoW请求数据来加载它需要的任何数据(或者从UoW的缓存中获得数据)。 虚拟机不必“思考”是要求数据的第一个还是最后一个,数据是否在缓存中,数据是在开始时还是根据需要检索。 UoW可以封装这些细节,展示虚拟机使用的简单“查询”方法。

  • 当然,UoW应该适当地提供“刷新”方法来应对过时...对于每种应用中的每种类型都有不同的定义。

  • 我们倾向于为每个通常围绕根实体定向的任务“沙盒”UoW。 因此,Parent-1的主虚拟机拥有自己的拥有自己的EntityManager的UoW,而Parent-2的主VM拥有自己的拥有自己的EntityManager的UoW。 通过这种方式,用户可以同时在Parent-1和Parent-2上工作(例如,在更新订单#456时创建订单#123)并独立进行而不会混淆变更。

  • “工作单元经理”使用嵌入式EntityManagers(EM)创建UoW。 它使用名为“EntityManagerProvider”的助手服务创建新的EM。 “EntityManagerProvider”负责创建新的EM并使用“全局数据”填充它们,例如参考列表(例如States,StatusCodes,Colors等)。

  • “EntityManagerProvider”(EMP)在内部保存一个只读的“主EM”,包含源MetadataStore和这些静态参考列表的规范版本。 它创建的新EMs通常是这个隐藏主EM的副本。 因此,整个系统对元数据和这些静态引用列表提出一个请求。 EMP负责将该来源资料分发给其创建的新EM。

  • 你需要多少钱? 我不知道。


    我的好友Steve Schmidt提供了一个必须考虑的替代攻击途径: 一个ViewModel / Multiple Views

    在这种方法中,您编写了不同的视图,每个视图都专用于对根对象及其子对象图形的特定视角。 这些与您原始提案的意见大致相同(如果不相同)。

    有什么不同? 只有一个ViewModel! Durandal的“ko compose”定制Knockout绑定将多个视图附加到同一个ViewModel是很容易的。 您可以在布局级别获得很好的分离,而无需使用站立式并行虚拟机。

    当提供模型的非可视化表示逻辑很简单,但您希望从不同的角度来看这个模型时(AKA,“围绕数据旋转”),这种方法很有效。

    主/细节可以是一个简单的例子。 设想一个参考列表编辑器,其顶部的“网格”中的列表项目和右侧的简单表格显示所选项目的详细信息。 这里没有太多的逻辑。 为什么要打扰两个虚拟机并且必须在“列表虚拟机”中将“虚拟机列表”中的项目列表与“编辑器虚拟机”中选定的项目进行协调? 作为单个虚拟机非常简单。

    在简单的情况下,这种方法非常有效,典型应用程序中有很多简单的情况。

    把它看作是对我的其他答案中描述的重型多VM技术的补充。

    链接地址: http://www.djcxy.com/p/50141.html

    上一篇: Nesting Multiple Views\ViewModels in Mvc4 and Knockout

    下一篇: Remove Extenders from in Knockout Observable (Knockout Validation)