MVC4局部视图中的Knockout绑定

Gen*_*ene 5 javascript asp.net-mvc-4 knockout.js

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

作为淘汰赛菜鸟很有可能(而且更广泛的是网络开发)我在这里缺少一个常见的javascript概念模式,但我遇到的场景非常类似于以下内容.我在服务器上有一个viewmodel,让我们说:

public class MainModel 
{
    // Other fields 

    SubviewModel Subview { get; set}
}

public class SubviewModel 
{
    // Relevant subview fields
}
Run Code Online (Sandbox Code Playgroud)

然后在强类型(主)部分视图中,我呈现我需要的任何内容,并通过@ Html.Action将子视图模型传递到强类型部分(在服务器上).在这两种情况下,我都是通过做这样的事情来设置淘汰赛:

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

ko.applyBindings(mvcModel , document.getElementById("@("divSubview"+Model.Guid)"));
Run Code Online (Sandbox Code Playgroud)

在这种情况下,divSubview将是部分的主要包装div,一切都通常绑定得很好 - 差不多.

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

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

那么我错过了什么是正确的解决方案?

我知道我可以使用Knockout的模板和一个更大的视图模型,最终可能是正确的解决方案,但是现在MVC部分(紧密耦合到服务器)有很多事情我不愿意给出起来.(其次我试图将部分内容尽可能松散地连接起来 - 至少在客户端上 - 即使我在绑定/等方面受到一点性能影响.)

(我认为)我真正想要的是将某种形式的范围传递给partials的方法,以便subview partial将引用主要的部分viewmodel(同样),而不必污染全局命名空间或使用unique名.有没有办法让我说一个客户端JS变量,它会引用子/父部分中的对象?(或者我完全忽略了这一点,还有更好的方法吗?)

Tom*_*all 1

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

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

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

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

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

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

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