我正在开发一个大型Web应用程序,我遇到了使用knockout和MVC正确构建它的问题。
我目前有一个基本视图模型,我将其传递到我的所有视图中,其中包含有关当前登录用户的基本数据
//Example Code
public class BaseViewModel {
public String FullName;
public String Email;
//A bunch of other similar values
}
然后我拥有特定于网站上每个页面的视图模型(即.profile)继承BaseViewModel类
//profile.cshtml
public class UserProfileViewModel : BaseViewModel {
public String Address;
public String PhoneNumber;
//Other similar values
}
//entity.cshtml
public class UserEntityViewModel : BaseViewModel {
public String EntityValue;
public Int32 EntityNumber;
//Other similar values
}
我使用knockout observables在javascript中重新定义了我的整个数据模型,这样我就可以在MVC模型中创建任何类型的对象。然后我在javascript中定义了几个与我的MVC视图模型基本相同的viewmodel,以允许加载,创建,编辑,删除功能。
我发现这在我想要从个人资料页面创建新实体的情况下非常有用。我可以创建一个viewmodel的新实例并将其绑定到一个新的jquery对话框,当单击OK按钮时,我可以在我的knockout viewmodel中调用一个将保存或创建实体的事件。
当我想将数据加载到特定页面时(即我想使用我的挖掘数据模型填充配置文件页面),这种架构不能很好地工作。我遇到了一些问题,我需要确定我所在的页面并将特定的viewmodel绑定到该页面。我真的不认为以下代码非常优雅。
$(function() {
if ($('.tweak-list').length) {
var id = $('.tweak-list').attr('data-songid');
var vm = new my.tweaksviewmodel({ songid: id });
ko.applyBindings(vm);
}
});
有没有人对我应该如何构建这个有任何建议?我认为最好在javascript中创建一个BaseViewModel并使用knockout映射插件http://knockoutjs.com/documentation/plugins-mapping.html自动创建我的各种数据模型。也就是说,它并没有真正解决确定模型绑定到哪个页面的问题,以便它可以加载适当的数据。
修改1
这个架构还有一个限制,我不能利用模态弹出窗口来添加数据,因为我需要将viewmodel重新绑定到每个模态..
有人有什么想法吗?
答案 0 :(得分:4)
我建议按照以下方式进行构建:
为每个页面创建一个具有特定KnockOut ViewModel的不同JavaScript模块:
var app = app || {};
app.pages = app.pages || {};
app.pages.userProfile = (function () {
function UserProfileViewModel() {
//view model specific code
};
function init() {
ko.applyBindings(new UserProfileViewModel());
};
return {
init: init
};
}());
指定应在剃刀视图中使用哪个JS模块:
@model dynamic
@{
ViewBag.CurrentPageJsHandler = "app.pages.userProfile";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<p>Page specific content</p>
将特定于页面的模块初始化代码添加到布局文件中:
<html>
<body>
<div id="content">
@RenderBody()
</div>
@if (@ViewBag.CurrentPageJsHandler != null)
{
<script>
$(function() {
app.currentPage = @ViewBag.CurrentPageJsHandler;
app.currentPage.init();
});
</script>
}
</body>
</html>
这样,您可以将所有与页面相关的代码封装在不同的模块中。由于每个JS模块都有唯一的名称,因此您可以将它们全部绑定在一起并包含在布局中。