阅读 25

JS递归实现DOM树状结构

HTML:

<ul class="tab">
    <li data-reply="publics">公有回复</li>
    <li data-reply="private">私有回复</li>
</ul>
<ul class="beTab">
    <li class="publics quickReply">
        <div class="labelbox">
            <p class="label allowOpen">一级标签1</p>
            <div class="labelbox">
                <p class="label allowOpen">二级标签2 - 1</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 1 - 1</p>
                    <p class="label">三级标签2 - 1 - 2</p>
                    <p class="label">三级标签2 - 1 - 3</p>
                </div>
                <p class="label allowOpen">二级标签2 - 2</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 2 - 1</p>
                    <p class="label">三级标签2 - 2 - 2</p>
                    <p class="label">三级标签2 - 2 - 3</p>
                </div>
                <p class="label allowOpen">二级标签2 - 3</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 3 - 1</p>
                    <p class="label">三级标签2 - 3 - 2</p>
                    <p class="label">三级标签2 - 3 - 3</p>
                </div>
                <p class="label allowOpen">二级标签2 - 4</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 4 - 1</p>
                    <p class="label">三级标签2 - 4 - 2</p>
                    <p class="label">三级标签2 - 4 - 3</p>
                </div>
            </div>
        </div>
        <div class="labelbox">
            <p class="label allowOpen">一级标签2</p>
            <div class="labelbox">
                <p class="label allowOpen">二级标签2 - 1</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 1 - 1</p>
                    <p class="label">三级标签2 - 1 - 2</p>
                    <p class="label">三级标签2 - 1 - 3</p>
                </div>
                <p class="label allowOpen">二级标签2 - 2</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 2 - 1</p>
                    <p class="label">三级标签2 - 2 - 2</p>
                    <p class="label">三级标签2 - 2 - 3</p>
                </div>
                <p class="label allowOpen">二级标签2 - 3</p>
                <div class="labelbox">
                    <p class="label">三级标签2 - 3 - 1</p>
                    <p class="label">三级标签2 - 3 - 2</p>
                    <p class="label">三级标签2 - 3 - 3</p>
                </div>
            </div>
        </div>
        <div class="labelbox">
            <p class="label allowOpen">一级标签3</p>
            <div class="labelbox">
                <p class="label allowOpen">二级标签2 - 1</p>
                <div class="labelbox">
                    <p class="label">三级标签3 - 2 -1</p>
                </div>
            </div>
        </div>
    </li>
    <li class="private quickReply"></li>
</ul>
复制代码

CSS:

.tab{ // 分类名 -- 公有回复、私有回复
  display: flex;
  width: 500px;
  height: 50px;
  li{
    height: 100%;
    flex: 1;
    display: flex;
    justify-content: center;
    align-items: center;
    border: 1px solid #ccc;
    border-left: none;
    cursor: pointer;
    transition: 0.5s;
    &:nth-child(1){
      border-left: 1px solid #ccc;
    }
    &:hover{
      background-color: #ccc;
    }
  }
}
.beTab{ // 公有回复私有回复内容区
  width: 500px;
  height: 500px;
  display: flex;
  li{
    flex: 1;
    height: 100%;
    .labelbox{
      padding-left: 20px;
      cursor: pointer;
      .label{
        margin: 10px 0;
        padding-left: 10px;
        &:hover{ // 每个标签名的鼠标滑过样式
          background-color: #f1f1f1;
        }
      }
      .label+.labelbox{ // 默认子级隐藏
        display: none;
      }
      .label.allowOpen{ // 拥有子级的,则拥有allowOpen类名,显示可展开icon
        position: relative;
        &:after{
          content: '';
          width: 26px;
          height: 26px;
          background-image: url("../images/slide.png");
          position: absolute;
          right: 100%;
          top: 0;
          transform: rotate(-90deg);
          transition: 0.3s;
        }
        &.open{ // 展开后的效果
          &:after{
            transform: rotate(0deg);
          }
        }
      }
      .label.open+.labelbox{ // 展开子级
        display: block;
      }
    }
  }
}
复制代码

JavaScript

  • 数据结构:
<!-- 后台返回还有其它的内容,但是这里对于生成DOM结构没用上,而且过多,就没写 -->

let data = {
    private:[
        {
            childCategories:[
                {
                    childCategories: [
                        {
                            childCategories: [],
                            id: 1011,
                            name: "英文问候1 - 1 - 1"
                        },
                        {
                            childCategories: [],
                            id: 1012,
                            name: "英文问候1 - 1 - 2"
                        }
                    ],
                    id: 101,
                    name: "英文问候1 - 1"
                }
            ],
            id: 100,
            name: "问候类 - 1"
        },
        {
            childCategories: [
                {
                    childCategories: [],
                    id: 201,
                    name: "英文问候2 - 1"
                },
                {
                    childCategories: [],
                    id: 202,
                    name: "英文问候2 - 2"
                },
                {
                    childCategories: [],
                    id: 203,
                    name: "英文问候2 - 3"
                }
            ],
            id: 200,
            name: "问候类 - 2"
        },
        {
            childCategories:[
                {
                    childCategories: [],
                    id: 301,
                    name: "英文问候3 - 1"
                },
                {
                    childCategories: [],
                    id: 302,
                    name: "英文问候3 - 2"
                }
            ],
            id: 300,
            name: "问候类 - 3"
        }
    ],
    public:[
        {
            childCategories: [
                {
                    childCategories: [],
                    id: 401,
                    name: "二级栏目1 - A"
                }
            ],
            id: 400,
            name: "一级栏目 - 1"
        },
        {
            childCategories:[],
            id: 500,
            name: "一级栏目 - 2"
        },
        {
            childCategories: [],
            id: 600,
            name: "一级栏目 - 3"
        }
    ]
}
复制代码
  • 创建DOM方法:
class createReplyDom {
    constructor(pub, pri){
        this.private = pri, // 私有快捷回复
        this.publics = pub  // 公开快捷回复
    }
    init(n){
        let beEle = document.getElementsByClassName('quickReply')[n];
        let obj = ((n == 1) ? this.private : this.publics)
        beEle.innerHTML =  `<div class="labelbox">${this.create(obj)}</div>` || ''
    }
    create(obj){
        let html = ''
        for(let p of obj){
            let allowOpen = ''
            if(p.childCategories.length > 0){
                allowOpen = 'allowOpen'
            }
            html += `<p class="label ${allowOpen}" data-id="${p.id}">${p.name}</p>`
            if(p.childCategories.length > 0){
                html += `<div class="labelbox">${this.create(p.childCategories)}</div>`
            }
        }
        return html
    }
}
复制代码
  • 调用:
let reply = new createReplyDom(data.public, data.private);
reply.init(1);
reply.init(0);
复制代码
  • 点击展开(使用了jQuery):
$(document).on('click',".quickReply .label.allowOpen", function () {
    if($(this).hasClass('open')){
        $(this).removeClass('open');
        return;
    }
    $(this).parents().siblings().find('.label').removeClass('open');
    $(this).addClass('open')
})
复制代码
关注下面的标签,发现更多相似文章
评论