MVC4局部视图中的Knockout绑定

时间:2012-10-22 04:37:51

标签: javascript knockout.js asp.net-mvc-4

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

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

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部分(紧密耦合到服务器)中有很多事情我不是愿意放弃。 (其次我试图尽可能保持部分松散耦合 - 至少在客户端上 - 即使我在绑定/等方面受到一点性能影响。)

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

1 个答案:

答案 0 :(得分:1)

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

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

你是不是可以逃脱单个绑定上下文并在页面中定义某种模块,该模块拥有顶级视图模型,并且子视图模型在子部分渲染时逐渐添加到其中,然后在底部页面,在DOM就绪,应用绑定?

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

我不确定你是否可以为这种结构安排某种页面级别管理器(如果你的意思是没有污染全局命名空间)。在任何情况下,让这些部分视图模型全部由单个对象拥有而不是浮动在全局命名空间中是不是很好? (如果是的话)

希望我能正确理解你的背景。

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