【问题标题】:Large Scale MVC Web Application - Using Knockout and Razor大规模 MVC Web 应用程序 - 使用 Knockout 和 Razor
【发布时间】:2013-01-23 16:57:22
【问题描述】:

我正在开发一个大型 Web 应用程序,但在使用 Knockout 和 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
}

我已经在 javascript 中使用敲除 observables 重新定义了我的整个数据模型,这样我就可以创建我在 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

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

有人有什么想法吗?

【问题讨论】:

    标签: jquery asp.net-mvc architecture knockout.js knockout-mapping-plugin


    【解决方案1】:

    我建议按照以下方式构建它:

    为每个页面创建具有特定 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 模块都有唯一的名称,您可以将它们绑定在一起并包含在布局中。

    【讨论】:

    • 我喜欢这个解决方案。我想我可以使用它的一部分。再次感谢!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多