knockoutjs 映射:在树中添加可观察对象

knockoutjs mapping: adding observables in a tree

我正在使用 knockoutjs 可视化一棵树。我有一个初始 AJAX-call 来加载洞树。使用 knockout-mapping-plugin 进行映射。一切正常 :) 感谢这款出色的软件。

我的问题是:我想向模型添加额外的可观察量。我可以使用映射选项来做到这一点。

Object:

{ id: ko.observable(), parentID: ko.observable(), description: ko.observable(), children: ko.observableArray() }

映射选项:

var mappingOptions = {
            create: function (options) {
                console.log("create");
                var vm = ko.mapping.fromJS(options.data);
                vm.newObservable = ko.observable(true);
                return vm;
            }
        };

映射:

ko.mapping.fromJS(response, mappingOptions, self.nodes);

response 是 objects(节点)的列表。 self.nodes 是包含 objects(nodes)

列表的 observableArray()

每个节点都有 children-observalbeArray 也包含节点(children) 所以没什么特别的,这基本上就是一棵树的工作原理:)

但这只会将这个新的可观察对象添加到根节点。我希望在每个 child 和 child 的 child(等等...)中也有这个额外的可观察对象。

我试过了:

var mappingOptions = {
    create: function (options) {
        console.log("create");
        var vm = ko.mapping.fromJS(options.data);
        vm.newObservable = ko.observable(true);
        return vm;
    },
    'children': {
        create: function (options) {
            console.log("children.create");
            options.data.newObservable = ko.observable(true);
            return ko.mapping.fromJS(options.data);                    
        }
    }
};

我在互联网上的某个地方找到了这个。它不起作用。

有人可以帮助我吗?

谢谢!

P.S.: 我无法提供 fiddle,因为该服务似乎已损坏(或者我的防火墙正在阻止它 :( )

我会尝试创建一个数据模型。我们称它为 Node:

var Node = function Node(data) {
  this.parentID    = ko.observable( data.parentID );
  this.description = ko.observable( data.description );
  this.children    = ko.observableArray([]);

  data.children.forEach(function(child) {
    this.children.push( new Node(child) );
  }, this);
}

这使得在您希望的每个节点上创建任何其他属性变得容易。

在您的视图模型中:

var Viewmodel = function Viewmodel() {
  this.nodes = ko.observableArray([]);

  this.getResponse = function getResponse() {
    // response is loaded here

    response.forEach(function(node) {
      this.nodes.push( new Node(node) );
    }, this);
  };
}

请注意,我在这里使用的是原生 Array.prototype.forEach。如果您需要支持 IE < 9,可以将其替换为 Knockouts ko.utils.arrayForEach