Knockout.js嵌套模型和可观察数组

时间:2013-05-20 05:31:12

标签: knockout.js

我是Knockout的新手并且在开始时遇到了一些问题。考虑以下模型:

// @param {String} content Content of the post
// @param {number} reply_to ID indicating to which post this post is replying
// @param {Array} replies Array of DiscussionPosts indicating replies to this post 
var DiscussionPost(content, reply_to, replies) {
    var self = this;
    self.content = content;
    self.reply_to = reply_to;
    self.replies = ko.observableArray(
        ko.utils.arrayMap(replies, function(reply) {
            return new DiscussionPost(reply.content, reply.reply_to, reply.replies);
        })

}

现在,对于我的视图模型,请考虑将我的所有帖子都放在名为allPosts的平面数组中,并尝试使用以前的模型构建结构,如下所示:

var rootPosts = allPosts.filter(function (o) {
    return o.reply_to === null;
});
var result = (function iterate(posts) {
    var tree = [];
    $.each(posts, function(i, post){
        var replies = allPosts.filter(function(o) {
            return o.reply_to === post.id;
        });
        if (replies.length > 0) {
            replies = iterate(replies);
        }

        var tmpPost = new DiscussionPost(post.content, post.reply_to, replies);
        tree.push(tmpPost);
    });
    return tree;
})(rootPosts);

理论上,result变量应包含所有帖子的图表,这些帖子的根目录中没有任何父级。例如,对于下面的树,它应返回一个带有一个元素即根的数组,然后它的回复应该是C1和C2,而C1的回复数组只能包含C3。问题是root是按预期填充的,其回复是C1和C2,但是C1的回复返回一个数组,其中包含四个DiscussionPost类型的元素,其中所有属性(content,reply_to和reply)都是未定义的。如果不是Knockouts的可观察数组,我在我的模型中使用常规的javascript数组,即使在100级深度也能正常工作。

    root
    / \ 
   /   \
  C1   C2
 /
C3  

1 个答案:

答案 0 :(得分:1)

非递归方法怎么样?

function DiscussionPost(post) {
    var self = this;
    self.content = ko.observable(post.content);
    self.reply_to = ko.observable(post.reply_to);
    self.replies = ko.observableArray([]);
}

var result = (function (posts) {
    var index = {}, root = "null";

    // root level
    index[root] = new DiscussionPost({});

    // transform into DiscussionPost objects, index by ID
    ko.utils.arrayForEach(posts, function (post) {
        index[post.id] = new DiscussionPost(post); 
    });

    // build tree
    ko.utils.arrayForEach(posts, function (post) {
        if (post.reply_to in index) {
            index[post.reply_to].replies.push(index[post.id]);
        } else {
            // orphaned post
        }
    });

    return index[root].replies;
})(allPosts);

对于大量帖子,这也应该更好。它比您的方法更容易阅读和调试。