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')
})
複製代碼
相關文章
相關標籤/搜索