【问题标题】:KnockoutJS: Converting an array to observableArrayKnockoutJS:将数组转换为 observableArray
【发布时间】:2011-07-18 05:41:52
【问题描述】:

这个问题建立在KnockoutJS: Tracking menu clicksKnockoutJS: Event object 之上。 我对代码进行了一些重构,以分离 viewModel 和 UI 逻辑。我现在要做的是将每个“Menu”对象的“Children”对象数组转换为 observableArray,这样我就可以添加/删除菜单的子项来更改我的 UI。

这是我的简化代码:

var viewModel = {};
var viewContext = {
    initialize: function (data) {
        viewModel = data;

        //for (var i = 0; i < viewModel.Panels.length; i++) {
            viewContext.observe(viewModel.Panels[0].Menu);
        //}
        viewModel.menuActive = ko.observable(false);
        viewModel.currentMenu = ko.observable(0);
        viewModel.currentNode = ko.observable({});
        viewModel.currentList = ko.observableArray([])
    },
    observe: function (data) {
        for (var i = 0; i < data.Children.length; i++) {
            viewContext.observe(data.Children[i]);
        }
        data.Children = ko.observableArray(data.Children);
    },
    nodeClicked: function (event) {
        var target = $(event.target)
        var data = target.tmplItem().data

        viewContext.getData(data, function (response) {
            viewModel.currentList(response.d);
            data.Children(response.d);
        });
        viewModel.currentNode(data);
    },
    getData: function (data, onSuccess) {
        $.ajax({
            url: 'console.asmx/' + data.Method,
            type: "POST",
            cache: false,
            contentType: "application/json; charset=utf-8",
            data: ko.utils.stringifyJson(data),
            dataType: "json",
            success: onSuccess,
            error: function () {
                viewModel.currentList([]);
            }
        });
    }
};
$(function () {
    $.ajax({
        url: 'console.asmx/Initialize',
        type: "POST",
        cache: false,
        contentType: "application/json; charset=utf-8",
        data: "{}",
        dataType: "json",
        success: function (data) {
            viewContext.initialize(data.d);
            ko.applyBindings(viewModel);
        }
    });
});

最初呈现页面时(使用引用问题中的模板),一切都很好。然而,当我点击一个触发“nodeClicked”事件的菜单时,我在data.Children(response.d); 行收到一个错误,上面写着“Uncaught ReferenceError: Children is not defined”

我的猜测是 data.Children = ko.observableArray(data.Children); 行没有正确地将我的数组转换为 observableArray。

任何想法将不胜感激。

【问题讨论】:

  • 在调用ko.observableArray(data.Children) 时是否定义了data.Children
  • 是的。数据在 ajax 调用后来自服务器,每个菜单对象都有一个属性“Children”,它是一个数组(如果是叶对象,则为空)。我可以确认这一点,因为我的 UI 针对绑定到 data.Children 的元素正确呈现。
  • 可以使用您正在使用的语法从数组创建 observableArray。它不应该引起问题。我会尝试在您的 AJAX 请求的回调中记录数据和 response.d,以确保它们符合您的期望。如果您将 Firefox 与 Firebug 或 Chrome 一起使用,一些 console.log 调用可能会有所帮助。否则,即使是回调中的一些 alert(ko.toJSON(data)) 也有望显示一些东西。也许将其添加到问题中。您的应用程序有点过于复杂,以至于其他人无法轻松地使用 jsFiddle 来模拟它。也许你可以试试。谢谢。
  • 感谢 RP!我认为您只是为我指明了正确的方向。
  • @RP Niemeyer,你是对的!我的 ajax 响应返回了一个在某些时候没有“儿童”属性的对象。我怎么能称赞你这个建议?您的评论可以成为答案吗?

标签: knockout.js jquery-templates


【解决方案1】:

可以使用您正在使用的语法从数组创建 observableArray。它不应该引起问题。我会尝试在您的 AJAX 请求的回调中记录数据和 response.d,以确保它们符合您的期望。如果您将 Firefox 与 Firebug 或 Chrome 一起使用,一些 console.log 调用可能会有所帮助。否则,即使回调中的一些 alert(ko.toJSON(data)) 也有望显示一些东西。如果说 Children 没有定义,那么将其从普通数组移动到 observableArray 就不仅仅是一个问题,因为 Chidren 根本不存在。

以下是可行和不可行的 sn-p:

$.getJSON("http://localhost/getMoreData", function (allData) {
  if (allData) {
    var mappedData = $.map(allData.rows, function (row) {
      return new Object();
    });

    // DOES NOT WORK:
    //self.koArray().unshift(mappedData);

    // DOES WORK!
    for (var i = 0; i < mappedData.length; i++) {
      self.koArray().unshift(mappedData[i]);
    }
  }
});

【讨论】:

  • 只是一个简短的评论 - 我需要使用我们的 REST 接口动态获取更多数据,然后将这些数据附加到我们的淘汰赛表中。我必须遍历数组并单独添加项目,而不是添加整个数组,以免 Knockout 抱怨。谢谢 RP。
猜你喜欢
  • 2012-04-10
  • 1970-01-01
  • 2018-05-13
  • 2015-05-18
  • 2013-02-03
  • 1970-01-01
  • 1970-01-01
  • 2018-10-06
相关资源
最近更新 更多