在经过MVC模式KnockoutJS最佳实践(Best practice on passing Mv

2019-06-26 12:30发布

我用Google搜索周围如何通过MVC模式knockoutjs,似乎有两种方式:

  • 使用@ Html.Raw(Json.Encode(型号))
  • 使用$不用彷徨或$阿贾克斯

其中的方法之一是通过MVC模式knockoutjs的最佳做法? 我知道这是一个按规定的基础,但它似乎使用$不用彷徨更清洁兑@ Html.Raw方法。

Answer 1:

我已经成功地使用了几种方法。

在一个强类型的Razor视图,你可以像你将任何其他HTML,插入模型元素,当您去编写JavaScript视图模型对象。 我觉得这klunky如剃刀和JS不与Visual Studio和智能感知以及一起玩,但即使有一串红squigglies产生的代码工作正常。

<script type="text/javascript">

var data = [
    @for (int i=0; i < Model.Packages.Count; i++)
    {
        var package = Model.Packages[i];
        <text>{Id: ko.observable(package.Id),
               Name: ko.observable(package.Name)
              }</text>
    }

    var viewModel = {
        var packages = ko.observableArray(data);
        // more code
    }

    ko.applyBindings(viewModel);
</script>

此代码可以在匆忙取决于模型的复杂性变得丑陋。 正如你所说,你也可以使用Html.Raw序列化模型对象为JSON()。 如果你走这条路线,你可以用它使用KO映射库来构建你的淘汰赛视图模型:

<script type="text/javascript">
    var data = @Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model));
    var viewModel = ko.mapping.fromJS(data);
    ko.applyBindings(viewModel);
</script>

这是不是第一个选项是缺憾,但我觉得我放弃了太多的控制权这种方式。 这意味着我的KO视图模型是相当紧耦合到我的MVC视图模型的结构,我可能会或可能不会要的。 更何况,这个工作我的JavaScript需要在我的CSHTML页,我真的不喜欢。 最后,这两种方法都是纯粹的服务器端。 为了更加适应网页,就像个SPI,你会希望做更多的客户端。

我的选择是使用$ .getJSON从自身的JavaScript调用客户端。 在这一点上,你可以处理返回的数据到您的视图模型,无论是手感还是滚动使用映射库。 如果要调用返回到你的MVC控制器动作,只是动作返回一个JsonResult类型(而不是一个ActionResult)。 (你也可以做类似的东西与ContentResult类型)如果你可以使用新的MVC4的WebAPI,这些控制器将默认返回JSON。



Answer 2:

@ Html.Raw当你想要的数据被作为实际的页面下载的一部分发送(Json.Encode(型号))被使用。 这可能会导致在你的页面需要更长时间来呈现给用户,但是当它呈现它应该是所有准备好了。

和$ .get或$就反而会得到数据,而网页显示。 这将创建一个单独的调用,这将导致你的页面更新它的渲染之后。

至于使用哪种..它取决于你的页面的布局方式,你是否没有把所有的数据在那里开始多久才能让您的数据与渲染你的页面。



Answer 3:

我的方法:

  • 视图模型是写在自己的JS文件,没有服务器端代码生成
  • 通过和$ .get或$就视图模型加载数据
  • 视图传递当其创建视图模型中的对象,并且该对象包含所有的服务器侧生成的URL

一个例子:

function MyViewModel(urls) {
    var self = this;
    self.isLoading = ko.observable(true);
    self.items = ko.observableArray();
    self.loadData = function() {
        $.get(urls.load, function(data) {
                // Process data and push into our items array
                self.isLoading(false);
            });
    }
}

var vm = new MyViewModel({
        load: '@Url.Action("GetData", "MyItemController")'
    });

$(function() {
    ko.applyBindings(vm);
    viewModel.loadData();
});

这意味着我有一个额外的AJAX调用的数据,但IMO用户逐渐认识到,数据!= UI。 好处是,我的用户界面,可以快速地提供出来,因为没有涉及到真正的数据访问。 根据数据库,数据量,等等,等等这也给我的代码关注一个非常干净的分离上的数据加载可能需要一段时间。



Answer 4:

我使用@ Html.Raw因为没有什么有用的,直到淘汰赛UI无论如何产生的用户可以在页面上做的,任何潜在的琐碎时间滞后,由于从写JSON到页面额外的初始下载是由用户补偿不看到一个令人不安的延迟UI建造之前。 我没有在所有问题与JSON用于构建我最初的视图模型在我的网页直接之中。

我哪里做的效率收益,仅从一个MVC控制器,然后把它由浏览器缓存独立的动态脚本下载获取的东西像选择选项(产品清单等)的任何可重复使用的参考数据。 他们可以在视图模型和视图模型被重用这样,只需要存储所选项目的值。



Answer 5:

我做的是一个Html.Raw,然后是js的对象我把它传递给我的淘汰赛JS模型。 事情是这样的:

//I'm using Newtonsoft library to serialize the objects
@{
    var jsModel = Newtonsoft.Json.JsonConvert.SerializeObject(Model);
}

<script type="text/javascript">
var model = @Html.Raw(jsModel);

var vm = new MyKnockoutModel(model);
ko.applyBindings(vm);

var MyKnockoutModel = function(model) {
    var self = this;
    this.Id = ko.observable(model.Id);
    this.Name = ko.observable(model.Name);
    this.Array1 = ko.observableArray(model.Array1);
}

</script>

我就是做这个的。



Answer 6:

正如你所说,这几乎是每一个要求的基础。

如果你正在做一个“一页应用”,你会做很多的$不用彷徨和$就调用,如果你只是渲染一个页面,它可能是更快地放在模型HTML,节省了额外的请求到服务器。

也取决于你有多少代码需要服务器端的,如果我的应用程序需要一个API,无论如何,我倾向于重用API和做$不用彷徨和$就调用,如果没有,我把模型中的HTML。



Answer 7:

老问题,但我认为我有模型数据传递给KO了视图模型,在一个可重用的时尚漂亮整洁的解决方案。 请注意,我用require.js为好。

添加的HtmlHelper扩展方法,在.NET:

using System.Web;
using System.Web.Mvc;
using System.Web.Script.Serialization;

namespace PROJECT.YOUR.EXTENSIONS.NAMESPACE {

    public static class HtmlHelperJavascriptExtensions {

        public static IHtmlString Serialize(this HtmlHelper helper, object obj) {
            return helper.Raw(new JavaScriptSerializer().Serialize(obj));
        }
    }
}

添加局部视图,KnockoutJsBinderPartial(我不得不使用ASPX):

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<PROJECT.Views.Shared.KnockoutJsBinderViewData>" %>
<%@ Import Namespace="PROJECT.YOUR.EXTENSIONS.NAMESPACE" %>

<script type="text/javascript">
    require(["Path/To/KnockoutJs", "<%= Model.ViewModelPath %>"], function (ko, ViewModel) {
        ko.applyBindings(new ViewModel(<%= Html.Serialize(Model.InnerModel) %>));
    });
</script>

由这种观点所引用的模型是:

namespace PROJECT.Views.Shared {

    public class KnockoutJsBinderViewData {

        public object InnerModel { get; private set; }

        public string ViewModelPath { get; private set; }

        public KnockoutJsBinderViewData(object innerModel, string viewModelPath) {
            InnerModel = innerModel;
            ViewModelPath = viewModelPath;
        }
    }
}

现在,你的.NET模型电汇到你的淘汰赛视图模型,所有你需要做的是:

<% Html.RenderPartial(
   "~/Views/Shared/KnockoutJsBinderPartial.ascx",
   new PROJECT.Views.Shared.KnockoutJsBinderViewData(
        Model, // The model from your strongly typed MVC view
        "Path/To/Knockout/ViewModel")); // The path to the Javascript file containing your view model
%>

请注意,包含您的视图模型不应该调用ko.applyBindings,应该返回构造函数的视图模型的JavaScript文件。 构造函数应该接受一个参数 - 你的JSON数据模型。



Answer 8:

在我的脑海里,希望保持HTML清洁,以避免内嵌JavaScript和数据混合。

我更喜欢用AJAX调用的端点注入数据。



文章来源: Best practice on passing Mvc Model to KnockoutJS