3

我正在开发一个大型 Web 应用程序,并且在使用淘汰赛和 MVC 正确构建它时遇到问题。

我目前有一个基本视图模型,我将它传递到我的所有视图中,其中包含有关当前登录用户的基本数据

//Example Code
public class BaseViewModel {
    public String FullName;
    public String Email;

    //A bunch of other similar values
}

然后,我拥有特定于站点上每个页面(即配置文件)的视图模型,它们继承了 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 视图模型基本相同的视图模型,以允许加载、创建、编辑、删除功能。

例如,我发现这在我想从个人资料页面创建新实体的情况下非常有用。我可以创建视图模型的一个新实例并将其绑定到一个新的 jquery 对话框,当单击确定按钮时,我可以在我的淘汰视图模型中调用一个将保存或创建实体的事件。

当我想将数据加载到特定页面(即,我想使用我的淘汰数据模型填充配置文件页面)时,这种架构效果并不好。我遇到了需要确定我所在的页面并将特定视图模型绑定到该页面的问题。我真的不认为下面的代码很优雅。

$(function() {
    if ($('.tweak-list').length) {
        var id = $('.tweak-list').attr('data-songid');
        var vm = new my.tweaksviewmodel({ songid: id });
        ko.applyBindings(vm);
    }
});

有人对我应该如何构建它有任何建议吗?我认为最好在 javascript 中创建一个 BaseViewModel 并使用敲除映射插件http://knockoutjs.com/documentation/plugins-mapping.html来自动创建我的各种数据模型。也就是说,它并没有真正解决确定模型从哪个页面绑定的问题,以便它可以加载适当的数据。

编辑 1

这种架构也有一个限制,我不能利用模式弹出窗口来添加数据,因为我需要将视图模型重新绑定到每个模式。

有人有想法么?

4

1 回答 1

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 模块都有唯一的名称,您可以将它们绑定在一起并包含在布局中。

于 2013-03-02T03:31:22.787 回答