【问题标题】:Knockout.js nested model and observable arraysKnockout.js 嵌套模型和可观察数组
【发布时间】:2013-05-20 05:31:12
【问题描述】:

我是 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。问题是根按预期填充,它的回复是 C1 和 C2,但是 C1 的回复返回一个包含四个 DiscussionPost 类型元素的数组,其中所有属性(内容、reply_to 和回复)都是未定义的。如果我在模型中使用常规 javascript 数组而不是 Knockouts 的 observable 数组,那么即使在 100 级深,一切都可以正常工作。

    root
    / \ 
   /   \
  C1   C2
 /
C3  

【问题讨论】:

    标签: knockout.js


    【解决方案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);
    

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

    【讨论】:

    • 谢谢托马拉克。是的,它有效。唯一的问题是您没有回答哲学问题,这就是为什么 Knockout 的可观察数组表现得如此奇怪。我很想知道背后的原因,而不是让代码工作。任何方式,感谢您的出色回答!
    • 用调试器应该很容易发现。我承认我没有这样做,但与可观察数组相比,递归问题更可能是递归问题。
    猜你喜欢
    • 2019-12-16
    • 2018-11-26
    • 1970-01-01
    • 1970-01-01
    • 2013-02-03
    • 2013-07-28
    • 1970-01-01
    • 2012-06-30
    • 1970-01-01
    相关资源
    最近更新 更多