如何创建嵌套的li-ul-li元素

时间:2014-06-18 03:26:58

标签: javascript recursion nested-lists

我希望采取以下json:

{
   "comments":[
      {
         "id":3,
         "comment":"asdasdasdasdsadsaasd",
         "author":"Adam",
         "post_id":126,
         "ancestry":null,
         "created_at":"2014-06-18T00:25:04.421Z",
         "updated_at":"2014-06-18T00:25:04.421Z",
         "children":[
            {
               "id":4,
               "comment":"asdasdasdasdsadsaasd",
               "author":"Adam",
               "post_id":126,
               "ancestry":"3",
               "created_at":"2014-06-18T00:25:57.913Z",
               "updated_at":"2014-06-18T00:25:57.913Z",
               "children":[
                  {
                     "id":7,
                     "comment":"asdasdasdasdsadsaasd",
                     "author":"Adam",
                     "post_id":126,
                     "ancestry":"3/4",
                     "created_at":"2014-06-18T00:57:36.277Z",
                     "updated_at":"2014-06-18T00:57:36.277Z",
                     "children":[

                     ]
                  },
                  {
                     "id":5,
                     "comment":"asdasdasdasdsadsaasd",
                     "author":"Adam",
                     "post_id":126,
                     "ancestry":"3/4",
                     "created_at":"2014-06-18T00:26:12.017Z",
                     "updated_at":"2014-06-18T00:26:12.017Z",
                     "children":[

                     ]
                  }
               ]
            }
         ]
      }
   ]
}

当你看到并编写一个递归函数来执行两件事时,可能会有更多的子项或注释嵌套:

  • 浏览每个评论博客寻找children,从那里走过那些 - 重复直到它的死胡同(函数应该是递归的 - 看看我到目前为止的内容)

  • 对于children中的每个孩子及其相关的孩子等等,这些元素应该有一个nested类,然后允许我执行以下操作:

    .nested .nested .nested .nested {/ * css规则这里有4个嵌套级别* /}

基本上我应该可以通过ulli来复制这种嵌套形式

我有什么?

我已经构建了一个反应组件mixin,它执行以下操作:

/**
 * Helps with abstracting certian logic from the comments component.
 */
var CommentsMixins = {

  commentElements: [],

  /**
   * Recursive fucntion to help get all nested comments.
   *
   * Keeps the order of the nested comments And renders a react component
   * which is a single comment.
   */
  renderComments: function(comments) {
    for (var key in comments) {
      if (key === 'children' && key.length !== 0) {
        var nestedComments = comments[key]
        for (var i = 0; i < nestedComments.length; i++) {
          this.commentElements.push('<li id="comment-'+nestedComments[i].id+'" class="indented"> <h1>'+nestedComments[i].author+' <small>said ... </small></h1>  <p>'+nestedComments[i].comment+'</p></li>');
          this.renderComments(nestedComments[i]);
        }
      }
  },

  getCommentElements: function() {
    return this.commentElements;
  }

}

这反过来会吐出来:

<ul>
  <li> ... </li> <!-- id: 3 -->
  <li> ... </li> <!-- id: 4 -->
  <li> ... </li> <!-- id: 7 -->
  <li> ... </li> <!-- id: 5 -->
  ...
</ul>

什么时候应该是这样的:

<ul>
 <li> <!-- id: 3 -->
   <ul>
     <li> ... </li> <!-- id: 4 -->
   </ul>
 </li>
 ...
<ul>

我需要在递归函数中更改以获得该类型的布局? (注意:您可以假设父ul已经完成呈现。所有li及其子孙等等都在外部呈现大多数<ul></ul>

1 个答案:

答案 0 :(得分:2)

以递归方式构建 - 不要输出到平面数组!

考虑使用jQuery的以下内容,因为它使DOM操作更容易。如果不使用jQuery,则使用其他DOM操作创建元素 tree ,因为这将表示所需的输出结构。 (YMMV;这种方法的理论是合理的,但它可能包含所写的错误。)

comments参数是一个数组,表示要处理的评论的当前级别(顶级response.commentscomment.children后人)。与原始方法不同,函数内部只有一个循环,因为它使用递归来遍历JSON 并将其转换为DOM ,一次一级/分支。

buildComments: function(comments) {
   // Return undefined if there are no comments to process;
   // alternatively, it /may/ be appropriate to return an empty UL.
   if (!comments || !comments.length) {
       return;
   }

   // Create the container UL for the comments in this level.
   var list = $('<ul>');
   for (var i = 0; i < comments.length; i++) { // Don't use for..in for arrays
       var comment = comments[i];

       // Create an LI for each comment and add it to the container
       var item = $('<li>')
           .attr('id', "comment-" + comment.id);
       // Add the LI to the UL parent
       list.append(item);
       // Add appropriate content to the item LI
       item.append($('<h1>').text(comment.author));
       item.append($('<p>').text(comment.comment));

       // And then do the same for each child level of comments..
       var childrenList = this.buildComments(comment.children);
       if (childrenList) {
           // ..adding children (UL) container to the current item (LI)
           item.append(childrenList);
       }
   }
   // Return container to be used by caller
   return list;
},

并像这样使用

var commentList = helper.buildComments(result.comments)
if (commentList) {
    $('#commentLocation').append(commentList);
}

如果顶级UL已经存在,则可能希望简单地附加结果(UL)元素的直接(LI)子元素。但是,这样做仍然是适应。