樹形菜單


  樹形菜單應該是很常見的了,類似下面這種,通常我們的做法是后端從數據庫中查詢出來數據,然后將其轉為樹的結構,丟給前端,前端就渲染到樹組件中;

 

  那么返給前端的數據是什么樣的呢?如下所示

[    {
          id: 1,
          label: '一級 1',
          children: [{
            id: 4,
            label: '二級 1-1',
            children: [{
              id: 9,
              label: '三級 1-1-1'
            }, {
              id: 10,
              label: '三級 1-1-2'
            }]
          }]
        },
    {xxx}

]    

 

 

  那么對應在數據庫中的表示什么樣子的呢?Subject表下圖所示,如果parent_id為0的,表示是一級菜單,其他多個二級菜單的parent_id等於某個一級菜單的id,依次類推,可有有很多級別菜單

 

 

下面用java代碼實現

  1.工具類:

package com.protagonist.edu.utils;

import com.protagonist.edu.bo.SubjectTreeNodeBO;
import com.protagonist.edu.entity.Subject;
import com.protagonist.responseVO.StatusCode;
import com.protagonist.servicebase.exception.ProtagonistException;
import org.springframework.beans.BeanUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 用於構建樹形結構
 */
public class TreeUtil {
    /**
     * 默認樹形菜單最頂層的pid是"0"
     * @param list 所有數據
     * @return 樹形的數據
     */
    public static  List<SubjectTreeNodeBO> buildTree(List<Subject> list) {
        if (CollectionUtils.isEmpty(list)){
            throw new ProtagonistException(StatusCode.ERROR,"查詢的菜單數據為空,不能轉為樹形");
        }
        return buildTree(list, "0");
    }

    /**
     *   獲取樹形菜單結構
     *      思路:首先遍歷一次將所有的數據轉化為前端需要的數據類型,然后放入到map中,以id->T對應關系
     *      然后再遍歷一次,這次的話判斷parentId是否為0(這里暫時可以特使pid為0時表示一級菜單),是的話就是一級菜單,就放到rootTree中;
     *      不為0的話,說明不是一級菜單,我們就需要獲取它的父菜單
     *      根據pid去map中獲取,然后將當前菜單放入其父菜單的子菜單中,等遍歷完之后樹形菜單就ok了,這種做法可以完成多級子菜單變成樹形
     * @param list 所有的數據
     * @param pid 父id
     * @return 樹形數據
     */
    public static  List<SubjectTreeNodeBO> buildTree(List<Subject> list, String pid) {
        if (CollectionUtils.isEmpty(list)){
            throw new ProtagonistException(StatusCode.ERROR,"查詢的菜單數據為空,不能轉為樹形");
        }
        List<SubjectTreeNodeBO> allTreeNode = new ArrayList<>();
        List<SubjectTreeNodeBO> rootTree = new ArrayList<>();
        Map<String, SubjectTreeNodeBO> nodeMap = new HashMap<>();
        //將所有的數據都放入到map中一份
        for (Subject item : list) {
            SubjectTreeNodeBO nodeBO = new SubjectTreeNodeBO();
            BeanUtils.copyProperties(item,nodeBO);
            allTreeNode.add(nodeBO);
            nodeMap.put(item.getId(),nodeBO);
        }
        for (SubjectTreeNodeBO t : allTreeNode) {
            //如果父id等於傳進來的pid,那么該菜單是最頂級的菜單,放入到rootTree中
            if (Objects.equals(t.getParentId(), pid)){
                rootTree.add(t);
                //如果不是頂級菜單,那就獲取父菜單,然后嫁給你本BO設置到父菜單的children中
            }else {
                SubjectTreeNodeBO parentNode = nodeMap.get(t.getParentId());
                parentNode.getChildren().add(t);
            }
        }
        return rootTree;
    }
}

 

   2.subject類:

@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
@TableName("subject")
@ApiModel(value="Subject對象", description="課程科目")
public class Subject implements Serializable {

    private static final long serialVersionUID = 1L;

    @ApiModelProperty(value = "課程類別ID")
    @TableId(value = "id", type = IdType.ID_WORKER_STR)
    private String id;

    @ApiModelProperty(value = "類別名稱")
    private String title;

    @ApiModelProperty(value = "父ID")
    private String parentId;

}

 

3.SubjectTreeNodeBO類:
package com.protagonist.edu.bo;

import lombok.Data;

import java.util.ArrayList;
import java.util.List;

@Data
public class SubjectTreeNodeBO {

    private String id;

    private String title;

    private String parentId;

    private List<SubjectTreeNodeBO> children = new ArrayList<>();
}

 

  4. 測試,成功,然后配合element的Tree 樹形控件一起使用,就行了

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM