You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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

火山引擎 最新活动