菜单允许编辑者在不更改站点模板的情况下管理有序链接。菜单有一个稳定的名称,如 primary 或 footer,每个翻译菜单有一组单独的项目。
创建菜单
在 EmDash 管理面板的 Menus 中创建和排列菜单。
-
点击 Create Menu 并输入名称和标签。模板查询名称,而标签在管理面板中标识菜单。
-
点击 Add Content 链接一个条目,或点击 Add Custom Link 输入外部 URL 或根相对站点路径。
-
使用 Move up 和 Move down 设置顺序。编辑项目并选择 Parent 来嵌套它。
在每个语言中使用相同的菜单名称。在多语言站点上,打开菜单并使用其 Translations 面板创建和编辑其他语言版本。EmDash 保持相同内容或分类术语的翻译相互连接,因此 getMenu() 可以使用请求语言的标签和 slug。
菜单链接如何解析
内容和分类菜单项存储的是引用而非完成的 URL。当模板调用 getMenu() 时,EmDash 使用当前集合和语言数据解析该引用。
| 菜单项类型 | 返回给模板的 URL |
|---|---|
| 内容条目 | 集合的 urlPattern,或当集合没有模式时为 /{collection}/{slug} |
| 分类术语 | 使用解析的术语翻译的 /{taxonomy}/{slug} |
| 集合归档 | /{collection}/ |
| 自定义链接 | 编辑者输入的外部 URL 或根相对路径 |
每个返回的项目还包含其标签、可选目标、title 属性、CSS 类和嵌套的 children。下面的渲染示例直接使用这些值。
渲染菜单
在服务器渲染的 Astro 组件中调用 getMenu()。当名称不存在时返回 null。
以下布局渲染一个主菜单和一级嵌套项目:
---
import { getMenu } from "emdash";
import { getRelativeLocaleUrl } from "astro:i18n";
const locale = Astro.currentLocale;
const menu = await getMenu("primary", { locale });
function menuHref(url: string) {
return locale && url.startsWith("/")
? getRelativeLocaleUrl(locale, url)
: url;
}
---
{menu && menu.items.length > 0 && (
<nav aria-label="主导航">
<ul>
{menu.items.map((item) => {
const href = menuHref(item.url);
return (
<li class:list={item.cssClasses}>
<a
href={href}
target={item.target}
rel={item.target === "_blank" ? "noopener noreferrer" : undefined}
title={item.titleAttr}
aria-current={Astro.url.pathname === href ? "page" : undefined}
>
{item.label}
</a>
{item.children.length > 0 && (
<ul>
{item.children.map((child) => {
const childHref = menuHref(child.url);
return (
<li class:list={child.cssClasses}>
<a
href={childHref}
target={child.target}
rel={child.target === "_blank" ? "noopener noreferrer" : undefined}
title={child.titleAttr}
aria-current={Astro.url.pathname === childHref ? "page" : undefined}
>
{child.label}
</a>
</li>
);
})}
</ul>
)}
</li>
);
})}
</ul>
</nav>
)}
getMenu() 首先选择显式的 locale,然后是当前请求语言,最后是配置的默认语言。如果该语言中缺少菜单或引用的条目,查找将遵循配置的回退链。
菜单项 URL 包含集合 URL 模式或分类路径,但不包含 Astro 的语言前缀。menuHref() 辅助函数将该前缀添加到根相对链接,并保持外部链接不变。
此示例渲染一级子项,涵盖典型的下拉菜单。如果编辑者可以创建更深层的导航,请将项目标记移到一个递归组件中,该组件使用相同规则渲染每个项目的 children。
在小部件区域中使用菜单
菜单小部件将现有菜单放置在小部件区域内。小部件读取当前请求语言的菜单。当站点需要自定义嵌套标记或显式语言 URL 处理时,使用上面的直接渲染模式。
直接查询菜单数据
当模板需要可用的菜单定义而不是一个菜单的项目时,使用 getMenus()。运行时 API 参考记录了查询签名和返回值。
对于编程式菜单更改,使用 Bearer 令牌进行身份验证,并在每个状态更改请求中添加 X-EmDash-Request: 1。请参阅菜单端点了解请求体和响应。
请参阅国际化了解语言路由和回退配置。