3

我有一个带有表格数据的网页。现在它使用 Knockout.js 绑定。

当页面加载时,我会调用 AJAX 来获取数据并进行绑定。基本上,页面首先显示,然后用户收到“正在加载...” ajax 消息和数据。这很好,因为页面加载速度很快,但浏览器必须对服务器进行 2 次调用(一个用于页面,另一个用于数据)。

如果用户想刷新数据 - 它也可以很好地工作。

我想知道如何将 ViewModel 数据与页面一起加载?有什么办法可以避免双重访问服务器?我想以某种方式在初始页面加载中包含 JSON,然后使用它并使用 AJAX 刷新它。

编辑:

我让它工作了,不确定我这样做是否有任何问题:

HTML:

<div id="initialData" style="display: none;"><asp:Literal ID="initialDataLiteral" runat="server" EnableViewState="False"/></div>

服务器代码:

// Prepare initial data for page
            var memoryStream = new MemoryStream();
            var serializer = new DataContractJsonSerializer(typeof(DataEnvelope));
            serializer.WriteObject(memoryStream, GetShipments(DateTime.Now.Date.AddMonths(-2).ToShortDateString(), DateTime.Now.Date.ToShortDateString()));
            memoryStream.Position = 0;
            var streamreader = new StreamReader(memoryStream);
            this.initialDataLiteral.Text = streamreader.ReadToEnd();

在淘汰赛方面很容易,我只需取出字符串,转换为 JSON 并使用它..

// Page comes with preloaded data. Let's set VM properties
        var initialData = $.parseJSON($("#initialData").text());
        vm.tripData(ko.utils.arrayMap(initialData.Shipments, function (i) { return new shipment(i); }));

稍后当用户点击刷新时,他们通过 AJAX 调用获得相同的数据。像这样拥有它有什么缺点吗?显然,查看源代码提供了一堆 JSON“东西”。与完全 ajaxed 加载相比,我仍然认为页面更紧凑,首次加载速度更快。

4

1 回答 1

1

您没有指定您使用的服务器端技术,但您至少使用asp.net. 这是我在 ASP.NET MVC 中使用的模式,因此如果您使用的是 Web 窗体,您可能需要对其进行调整。

var modelData = @Html.Raw(Json.Encode(Model));

var MyViewModel = function (data) {
    var model = ko.mapping.fromJS(data);

    // any additional observables, computeds, methods, etc., i.e.
    // model.SomethingNotOnModel = ko.computed();

    return model;
};

var viewModel = MyViewModel(modelData);
ko.applyBindings(viewModel);

Knockout 的映射插件将自动为提供给它的数据对象上存在的任何属性创建可观察对象,因此您无需手动指定这些属性,除非您需要更改它们。

更新

根据@Rich 的评论,我觉得我应该更清楚地展示你应该如何实际使用它:

在页面中

<script>
    $(document).ready(function () {    
        var modelData = @Html.Raw(Json.Encode(Model));
        MyApp.MyView.Init(modelData);
    });
</script>

外部 JS

MyApp = MyApp || {};

MyApp.MyView = function () {
    var _init = function (data) {
        var viewModel = MyApp.MyView.MyViewModel(data);
        ko.applyBindings(viewModel);
        // anything else that should happen on page load
    };

    return {
        Init: _init
    };
}();

MyApp.MyView.MyViewModel = function (data) {
    var model = ko.mapping.fromJS(data);

    // any additional observables, computeds, methods, etc., i.e.
    // model.SomethingNotOnModel = ko.computed();

    return model;
};
于 2013-04-18T18:18:53.417 回答