我正在尝试将我的MVC应用程序的_Layout页面转换为使用knockout viewmodel而不是Razor语法。到目前为止,我的所有内容页面都具有如下语法来呈现javascript ViewModels(用于索引视图):
<script type="text/javascript">
$(document).ready(ko.applyBindings(new IndexVm(
@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })))));
</script>
到目前为止,这项工作一直很顺利。现在,在我的布局中,我尝试使用相同的方法:
<script type="text/javascript">
$(document).ready(ko.applyBindings(new LayoutVm(
@Html.Raw(JsonConvert.SerializeObject(ViewBag, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() })))));
</script>
如果内容页面没有内部viewmodel声明,则此方法有效。但是当我加载索引页面(带有第一个片段)时,我得到以下内容:
未捕获错误:您无法多次将绑定应用于同一元素。
我有点难过为什么这不起作用。任何帮助将不胜感激!
答案 0 :(得分:2)
您必须了解ASP.NET在将HTML文档发送到浏览器之前将在服务器上完成某些任务。它将解释Razor语句,并将部分视图,视图和布局组合成服务器上的单个HTML文档。
Knockout是在客户端(浏览器)上运行的框架。如果您在 _Layout.cshtml 和 Index.cshtml 中应用绑定,则会在汇编的HTML文档中应用绑定两次。在Knockout中,您不能在相同的HTML元素上多次应用绑定。
您需要做的是向某些HTML元素添加具有有意义值的id属性。然后,您需要向您的不同ko.applyBindings添加第二个参数,这将是元素ID。
现在,如果您遇到嵌套元素,则可以自己控制降序绑定。您可以指定一个语句,该语句将停止父元素与子元素的绑定。请在http://www.knockmeout.net/2012/05/quick-tip-skip-binding.html上了解详情。
答案 1 :(得分:1)
你可以通过在html中提供占位符来实现这一点:
<div id="index">
<!-- index page goes here -->
</div>
和
<div id="layout">
<!-- layout page goes here -->
</div>
然后您可以按如下方式应用视图模型:
<script type="text/javascript">
$(document).ready(ko.applyBindings(new IndexVm(
@Html.Raw(JsonConvert.SerializeObject(Model, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }))), document.getElementById('index')));
</script>
和
<script type="text/javascript">
$(document).ready(ko.applyBindings(new LayoutVm(
@Html.Raw(JsonConvert.SerializeObject(ViewBag, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }))), document.getElementById('layout')));
</script>
答案 2 :(得分:0)
ko.applyBindings
可以有两个参数,第一个是您的viewmodel,第二个是要设置的绑定上下文的可选根节点。如果未提供任何值,则根节点默认为window.document.body
。如果在没有指定不同根节点的情况下调用applyBindings两次,那么它将为您提供接收的错误。
请记住,您不希望重叠绑定的节点。如果需要为两个单独的视图模型调用applyBindings两次,则必须指定要绑定的不同元素:
ko.applyBindings(new MenuVM(), document.getElementById('menu'));
ko.applyBindings(new ContentVM(), document.getElementById('sub-content'));
修改强> 根据rwisch45的评论,一个选项是将一个视图模型绑定到整个页面,并在主视图模型中设置子视图模型。