我是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
答案 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);
对于大量帖子,这也应该更好。它比您的方法更容易阅读和调试。