Aurelia中构建导航菜单:基于WordPress API的实现方案咨询
实现Aurelia + WordPress API的多级导航菜单
我之前正好做过类似的需求,完全明白你说的“只有单行菜单资料”的痛点——多级菜单才是实际项目里的常态,下面分享我的实践步骤和思路:
第一步:WordPress端配置(确保API返回完整的菜单层级)
首先得让WordPress的REST API返回带层级结构的菜单数据,而不是扁平列表。用插件或者自定义端点都可以,我更推荐自定义端点,灵活性更高:
- 在主题的
functions.php里注册一个自定义REST路由,把扁平的菜单数据转成树形结构(这是关键):
add_action('rest_api_init', function () { register_rest_route('custom/v1', '/menu/(?P<slug>[a-zA-Z0-9-]+)', array( 'methods' => 'GET', 'callback' => 'get_custom_menu_data', )); }); function get_custom_menu_data($request) { $menu_slug = $request['slug']; $menu_locations = get_nav_menu_locations(); $menu_id = $menu_locations[$menu_slug]; // 获取所有菜单项 $menu_items = wp_get_nav_menu_items($menu_id); // 转成带children的树形结构 $menu_tree = array(); $menu_item_map = array(); foreach ($menu_items as $item) { $menu_item_map[$item->ID] = array( 'id' => $item->ID, 'title' => $item->title, 'url' => $item->url, 'children' => array(), 'parent_id' => $item->menu_item_parent ); } foreach ($menu_item_map as $item_id => $item) { if ($item['parent_id'] != 0) { $menu_item_map[$item['parent_id']]['children'][] = $item; } else { $menu_tree[] = $item; } } return rest_ensure_response($menu_tree); }
现在调用/wp-json/custom/v1/menu/你的菜单位置slug,就能拿到包含children字段的层级菜单数据了。
第二步:Aurelia端实现多级菜单渲染
核心思路是用递归组件处理不确定层级的菜单,这样不管是2级还是N级都能适配。
1. 写一个菜单数据服务
先做个服务拉取WordPress的菜单数据,比如menu-service.js:
import { HttpClient } from 'aurelia-fetch-client'; export class MenuService { constructor(http) { this.http = http; this.http.configure(config => { config .withBaseUrl('/wp-json/custom/v1/') .withDefaults({ headers: { 'Accept': 'application/json' } }); }); } async getMenu(slug) { const response = await this.http.fetch(`menu/${slug}`); return await response.json(); } }
2. 递归菜单项组件
创建nav-menu-item.html和对应的JS,用来渲染单个菜单项,有子菜单就递归调用自己:
<template> <li class="nav-item"> <a href="${item.url}" class="nav-link">${item.title}</a> <!-- 存在子菜单时递归渲染 --> <ul if.bind="item.children && item.children.length > 0" class="submenu"> <nav-menu-item repeat.for="child of item.children" item.bind="child"></nav-menu-item> </ul> </li> </template>
import { bindable } from 'aurelia-framework'; export class NavMenuItem { @bindable item; }
3. 主导航组件
在主导航里调用服务获取数据,渲染顶级菜单项:
<template> <nav class="main-nav"> <ul class="nav-list"> <nav-menu-item repeat.for="item of menuItems" item.bind="item"></nav-menu-item> </ul> </nav> </template>
import { inject } from 'aurelia-framework'; import { MenuService } from './menu-service'; @inject(MenuService) export class MainNav { menuItems = []; constructor(menuService) { this.menuService = menuService; } async attached() { // 替换成你的菜单位置slug this.menuItems = await this.menuService.getMenu('primary'); } }
第三步:样式优化(可选但实用)
给多级菜单加基础样式,比如子菜单默认隐藏、hover显示,再做移动端适配:
.main-nav .nav-list { list-style: none; display: flex; gap: 1.5rem; } .submenu { position: absolute; list-style: none; display: none; background: #fff; padding: 0.8rem; border-radius: 6px; box-shadow: 0 3px 10px rgba(0,0,0,0.1); } .nav-item:hover .submenu { display: block; } /* 移动端适配 */ @media (max-width: 768px) { .main-nav .nav-list { flex-direction: column; } .submenu { position: static; margin-left: 1.2rem; } }
额外小提示
- 如果菜单里有自定义链接、分类或文章,上面的PHP代码都能处理,因为
wp_get_nav_menu_items会返回所有类型的菜单项数据。 - 可以给Aurelia加个加载状态,比如在获取菜单时显示加载动画,提升体验。
- 要实现当前页面菜单项高亮的话,可以监听Aurelia路由变化,对比当前路由和菜单项URL,给对应的项加
active类。
内容的提问来源于stack exchange,提问作者Jim Shelly




