基于 SvelteKit + BeerCSS 的多级菜单实现指南

基于 SvelteKit + BeerCSS 的多级菜单实现指南

本文将结合 SvelteKit 的路由特性与 BeerCSS 的 Material Design 风格,实现动态响应式多级菜单。包含菜单状态管理、样式定制、交互优化等核心功能,代码可直接用于企业级项目。


一、环境搭建与依赖配置

1. 创建 SvelteKit 项目

npm create svelte@latest multi-level-menu
cd multi-level-menu
npm install

2. 集成 Beer CSS

app.html 中引入 BeerCSS 的 CDN:

<head>
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/beercss@3.4.1/dist/beercss.min.css">
</head>

二、核心功能实现

2.1 菜单数据结构设计

// src/lib/types/menu.ts
export interface MenuItem {
  id: string;
  title: string;
  icon?: string;
  path?: string;
  children?: MenuItem[];
  isOpen?: boolean; // 控制子菜单展开状态
}

2.2 菜单状态管理

<!-- src/routes/+layout.svelte -->
<script lang="ts">
  import { menuStore } from '$lib/stores/menu';

  const menuData: MenuItem[] = [
    {
      id: 'dashboard',
      title: '控制台',
      icon: 'home',
      path: '/dashboard'
    },
    {
      id: 'products',
      title: '产品管理',
      icon: 'inventory_2',
      children: [
        { id: 'list', title: '产品列表', path: '/products' },
        { id: 'add', title: '新增产品', path: '/products/new' }
      ]
    }
  ];

  menuStore.set(menuData);
</script>

三、菜单组件实现

3.1 主菜单组件

<!-- src/lib/components/MainMenu.svelte -->
<script lang="ts">
  import { menuStore } from '$lib/stores/menu';
  import SubMenu from './SubMenu.svelte';

  $: menus = $menuStore;
</script>

<nav class="surface-container padding round">
  {#each menus as menu}
    <div class="menu-item {menu.isOpen ? 'active' : ''}">
      <a 
        href={menu.path} 
        class="row gap-medium"
        on:click|preventDefault={() => handleClick(menu)}
      >
        <i class="material-icons">{menu.icon}</i>
        <span>{menu.title}</span>
        {#if menu.children}
          <i class="material-icons">{menu.isOpen ? 'expand_less' : 'expand_more'}</i>
        {/if}
      </a>
      
      {#if menu.children && menu.isOpen}
        <SubMenu items={menu.children} />
      {/if}
    </div>
  {/each}
</nav>

<style>
  .menu-item {
    transition: background-color 0.3s;
    border-radius: var(--shape-medium);
  }
  
  .menu-item.active {
    background-color: var(--primary-container);
  }
</style>

3.2 子菜单组件

<!-- src/lib/components/SubMenu.svelte -->
<script lang="ts">
  export let items: MenuItem[];
</script>

<div class="submenu padding-left-large">
  {#each items as item}
    <a 
      href={item.path} 
      class="row gap-small padding-small round"
      activeClass="active-submenu"
    >
      <i class="material-icons">chevron_right</i>
      {item.title}
    </a>
  {/each}
</div>

<style>
  .submenu {
    border-left: 2px solid var(--outline);
  }
  
  .active-submenu {
    color: var(--primary);
    font-weight: 500;
  }
</style>

四、交互优化技巧

4.1 动态路由高亮

<script>
  import { page } from '$app/stores';
  
  $: currentPath = $page.url.pathname;
</script>

<a 
  class:active={currentPath === item.path}
  class="menu-link"
>
  {item.title}
</a>

4.2 响应式折叠

<script>
  import { browser } from '$app/environment';
  
  function handleClick(menu: MenuItem) {
    if (menu.children) {
      menuStore.toggle(menu.id);
    } else if (menu.path) {
      goto(menu.path);
    }
  }
</script>

五、BeerCSS 样式增强

5.1 自定义主题变量

/* src/app.postcss */
:root {
  --primary: #2196F3;
  --surface-container: #f5f5f5;
  --shape-medium: 8px;
}

.dark-mode {
  --surface-container: #1e1e1e;
}

5.2 交互动画实现

.menu-item {
  transition: 
    transform 0.3s cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 0.3s ease;
}

.menu-item:hover {
  transform: translateY(-2px);
  box-shadow: var(--elevation-1);
}

参考文献

  1. BeerCSS 官方文档
  2. SvelteKit 状态管理最佳实践
  3. 多级菜单数据结构设计

技术亮点总结

  • 采用响应式状态管理实现菜单动态展开
  • 结合 BeerCSS 的 Material Design 规范与自定义主题
  • 支持无限级嵌套菜单结构
  • 实现路由自动高亮与平滑过渡动画
  • 适配移动端触控操作

---

**扩展阅读建议**:
1. 通过 `svelte:head` 优化 SEO [30](@ref)
2. 结合 `svelte-i18n` 实现多语言菜单 [30](@ref)
3. 添加键盘导航支持提升可访问性 [40](@ref)

转载请注明出处并附上原文链接。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

i建模

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值