選單產生方式

遞迴

by ph822720355

HTML

<ul id="menu"></ul>

JavaScript

// [全域變數] 假資料
const mockData = [
    { id: '1', parentId : '0', label: '基本功能', url: 'homepage/index' },
    { id: '2', parentId : '1', label: '使用者管理', url: 'subpage1/index' },
    { id: '3', parentId : '1', label: '權限管理', url: 'subpage2/index' },
		{ id: '4', parentId : '0', label: '進階功能', url: 'homepage/index' },
    { id: '5', parentId : '4', label: '債務試算', url: 'subpage1/index' },
    { id: '6', parentId : '4', label: '報表', url: 'subpage2/index' },
		{ id: '7', parentId : '6', label: '列印', url: 'subpage2/index' },
];

//	[全域變數] Menu
let globalMenuList = [];

/* [方法] 建立Menu */
function buildMenuTree(flatData, includeRoot = true) {
    // 定義根節點
    const root = {
        label: '目錄清單',
        id: 0,
        parentId: null,
        children: []
    };

    // 創建一個物件,以id為鍵來存放每一個節點,方便後續直接查找節點
    const nodesById = {};

    // 一次遍歷來構建nodesById和初始化節點
    flatData.forEach(item => {
        nodesById[item.id] = {
            ...item,
            routUrl: `Controller/${item.url}`,
            children: []
        };
    });

    // 遍歷所有節點,將它們放到適當的父節點或根節點下
    flatData.forEach(item => {
        const node = nodesById[item.id];

        if (item.parentId === '0') {
            root.children.push(node);
        } else if (nodesById[item.parentId]) {
            nodesById[item.parentId].children.push(node);
        }
    });

    // 若includeRoot為true,回傳包含根節點的陣列;否則僅回傳根節點的子節點
    return includeRoot ? [root] : root.children;
}


// [方法] 遞迴函數來建立HTML清單
function createMenuList(items) {
  const ul = document.createElement('ul');

  items.forEach(item => {
    const li = document.createElement('li');
    const a = document.createElement('a');
    a.href = item.url;
    a.textContent = item.label;
    li.appendChild(a);

    if (item.children && item.children.length > 0) {
      const childUl = createMenuList(item.children);
      li.appendChild(childUl);
    }

    ul.appendChild(li);
  });

  return ul;
}


// 取得不包含 根結點 的選單
globalMenuList = buildMenuTree(mockData, false)
// 取得不包含...