5

简而言之,我相信我追求的是一种在 MVC4 部分视图中为敲除绑定/javascript 对象提供范围/上下文的方法,这样我就可以重用相同的部分而不会让它们相互干扰,但仍然能够在客户端引用父子视图模型。

作为一个淘汰的菜鸟(更广泛地说是真正的网络开发人员),我很可能在这里错过了一个常见的 javascript 概念模式,但我遇到的场景很像下面这样。我在服务器上有一个视图模型,让我们说一下:

public class MainModel 
{
    // Other fields 

    SubviewModel Subview { get; set}
}

public class SubviewModel 
{
    // Relevant subview fields
}

然后在强类型(主)部分视图中渲染我需要的任何内容,并通过@Html.Action 将子视图模型传递到强类型部分(在服务器上)。在这两种情况下,我都通过执行以下操作来设置淘汰赛:

var mvcModel = ko.mapping.fromJS(@Html.Raw(JsonConvert.SerializeObject(this.Model)));

ko.applyBindings(mvcModel , document.getElementById("@("divSubview"+Model.Guid)"));

在这种情况下, divSubview 将是部分的主要包装 div 并且所有内容通常都绑定得很好 - 几乎。

Model.Guid 连接用于解决第一个问题,即这些部分通常在页面上针对不同的视图模型呈现多个。(把它想象成一个项目列表,一个待办事项列表或诸如此类的东西,其中每个项目都有可能改变的子内容 - 你可能会明白,可能在我试图进一步解释之前......)所以当多个部分呈现在同一页面上时,如果 div 不是唯一命名的,如果我通过 document.getElementById 调用 applyBindings,我最终会将第二个 viewModel 应用到具有该名称的第一个渲染 div。

第二个问题是相关的,因为当我渲染主要部分(给定页面有多个),然后是子视图时,我经常想引用子视图中的主视图模型或类似的。我一直在使用的解决方法只是设置一个命名的全局参数,然后使用它来来回引用,因为我知道脚本将按顺序执行 - 但这很hacky。

那么我缺少什么正确的解决方案?

我知道我可以只使用 Knockout 的模板和一个更大的视图模型,最终这可能是正确的解决方案,但目前在 MVC 部分(与服务器紧密耦合)中有很多事情我不愿意给出向上。(其次,我现在试图使部分尽可能松散耦合 - 至少在客户端上 - 即使我在绑定/等方面受到了一些性能影响。)

什么(我认为)我真正追求的是一种将某种形式的范围传递给局部的方法,这样子视图局部将具有对主要局部视图模型的引用(同样),而不必污染全局命名空间或使用唯一的名字。有没有办法让我说表示客户端 JS 变量将引用子/父部分中的对象?(或者我是否完全错过了这一点并且有更好的方法?)

4

1 回答 1

1

从长远来看,最好咬紧牙关,使用映射插件的经典组合,渲染到页面中的顶级视图模型的 JSON 表示以进行初始化,以及子视图模型的模板。但我理解你对现有 MVC 部分逻辑的痛苦,所以......

您当前是否将单独的脚本块渲染为每个子部分视图的一部分以创建其 Knockout 视图模型并应用其绑定?

您能否摆脱单个绑定上下文并在页面中定义某种模块,该模块拥有顶级视图模型,并在子部分渲染时逐渐添加其子视图模型,然后在页面底部,在 DOM 准备好时,应用绑定?

因此,每个子部分的脚本块都会调用模块上的某个函数,传入子模型的原始 JSON,其中包括其 Guid 键。然后,您的模块创建子视图模型的新实例并将父视图模型设置为其中的引用,并将其推送到父视图模型上的子视图模型的可观察数组中。然后你有每一种方式的参考。

我不确定您是否可以为这种结构使用某种页面级管理器(如果这就是您不污染全局命名空间的意思)。无论如何,让这些局部视图模型全部由单个对象拥有而不是漂浮在全局命名空间中不是很好吗?(如果它们是)

希望我正确理解您的上下文。

更新:从某种意义上说,您的部分仍然是松散耦合的。标记中的绑定表达式显然必须与子视图模型的实例相关,但这可能是通过待办事项列表项上的 foreach 链接下来的数据上下文或其他内容,或者使用“with”表达式显式设置,例如使用 someOtherModule.randomStandaloneSubViewModel

于 2012-11-16T23:00:52.277 回答