樹形菜單應該是很常見的了,相似下面這種,一般咱們的作法是後端從數據庫中查詢出來數據,而後將其轉爲樹的結構,丟給前端,前端就渲染到樹組件中;前端
那麼返給前端的數據是什麼樣的呢?以下所示java
[ { 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,依次類推,可有有不少級別菜單node
下面用java代碼實現spring
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 樹形控件一塊兒使用,就好了工具