9

我正在开始一个新项目,并且热衷于使用对我来说是新的 KnockoutJS + Web Api,我对 Web Api 有很好的了解,但是目前很难理解 Knockout。

这是我希望我的应用程序如何工作的最初想法:

  • 我有一个标准的 MVC 控制器,例如LeadsController
  • LeadsController有一个Action被调用的ListLeads,这实际上并没有返回任何数据,而只是返回一个带有模板的视图来显示来自 Knockout 的数据。
  • ListLeads视图通过 ajax 调用我的 api 控制器以LeadsApiController获取要显示的潜在客户列表
  • 然后将潜在客户数据映射到 KnockoutJs ViewModel(我不想将我的视图模型从服务器端复制到 JavaScript 视图模型中)
  • 我想尽可能多地使用外部 JavaScript 文件,而不是让我的 HTML 页面充满 JavaScript。

我见过很多例子,但大多数都是在第一页加载时返回一些初始数据,而不是通过 ajax 调用。

所以我的问题是,当从 ajax 检索时,如何为 Knockout 创建我的 JavaScript viewModel,其中 ajax url 是使用Url.Content().

另外,如果我需要在这个 ViewModel 上附加计算值,我将如何从服务器端扩展映射的视图模型。

如果我没有很好地解释自己,请让我知道您不确定的内容,我会尝试更新我的问题以更明确。

4

2 回答 2

5

我认为你的设计是个好主意。事实上,我现在正在使用这种设计开发一个应用程序!

您不必在页面中嵌入初始数据。相反,当您的页面加载时,创建一个空视图模型,调用ko.applyBindings,然后启动 AJAX 调用,该调用将在完成时填充视图模型:

$(function () {
    var viewModel = {
        leads: ko.observableArray([]) // empty array for now
    };

    ko.applyBindings(viewModel);

    $.getJSON("/api/Leads", function (data) {
        var newLeads = ko.mapping.fromJS(data)(); // convert to view model objects
        viewModel.leads(newLeads); // replace the empty array with a populated one
    });
});

在 AJAX 调用完成之前,您需要在页面的某处放置一条“正在加载”消息。

要生成“/api/Leads” URL,请使用Url.RouteUrl

<script>
    var apiUrl = '@Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Leads" })';
</script>

(假设您在 Global.asax 或 App_Start\RouteConfig.cs 中配置的 API 路由命名为“DefaultApi”。)

上面使用了敲除映射插件将 AJAX JSON 结果转换为敲除视图模型。默认情况下,生成的视图模型对于 JSON 中的每个属性都有一个可观察的属性。要对此进行自定义,例如添加额外的计算属性,请使用敲除映射插件的“创建”回调

在我的应用程序中做到这一点之后,我发现我想要更多来自服务器端视图模型的元数据,这些元数据可用于客户端代码,例如需要哪些属性,以及每个属性有哪些验证。在剔除映射“创建”回调中,我想要这些信息以便在视图模型中自动生成额外的属性和计算的 observables。因此,在服务器端,我使用了一些 MVC 框架类和反射来检查视图模型并生成一些元数据作为嵌入到相关视图中的 JavaScript。在客户端,我有外部 JavaScript 文件,它们连接敲除映射回调并根据页面中提供的元数据生成视图模型。我的建议是首先在每个视图中手动编写淘汰视图模型自定义和其他 JavaScript,然后在重构时将通用 JavaScript 函数移到外部文件中。每个视图最终都应该只包含特定于该视图的最小 JavaScript,此时您可以考虑编写一些 C# 来从服务器端视图模型注释生成该 JavaScript。

于 2012-08-17T12:09:00.640 回答
1

对于 url 问题,将其添加到您的 _Layout.cshtml 中,该位置位于将使用它的文件之前:

<script>
    window._appRootUrl = '@Url.Content("~/")';
</script>

然后,您可以使用window._appRootUrl字符串连接或借助 URI.js 之类的 JavaScript 库来编写 url。

至于额外的计算值,您可能希望使用剔除计算的 observable。如果这是不可能的,或者您更喜欢在 .Net 中执行此操作,您应该能够仅使用 getter 创建一个属性,但是当您更新客户端上的其他属性(如果它依赖于它们)时,这不会更新。

于 2012-08-17T02:43:23.733 回答