You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何基于JSON实现Flutter动态多级抽屉菜单(适配不同角色)

Flutter 基于JSON动态渲染角色专属多级抽屉菜单实现方案

核心思路

先定义统一的JSON菜单结构(包含层级、角色权限、路由等信息),解析为Dart实体类后,根据当前用户角色过滤出可访问的菜单,最后通过插件或自定义组件渲染多级抽屉。

具体实现步骤

1. 定义标准化JSON菜单结构

设计包含角色权限、层级关系的JSON格式,示例如下:

[
  {
    "id": 1,
    "title": "首页",
    "icon": "home",
    "route": "/home",
    "roles": ["admin", "user"],
    "children": []
  },
  {
    "id": 2,
    "title": "管理中心",
    "icon": "settings",
    "roles": ["admin"],
    "children": [
      {
        "id": 21,
        "title": "用户管理",
        "icon": "person",
        "route": "/admin/users",
        "roles": ["admin"],
        "children": []
      }
    ]
  }
]

2. 解析JSON为Dart实体类

使用json_serializable包生成序列化模型,简化JSON解析:

import 'package:json_annotation/json_annotation.dart';

part 'menu_model.g.dart';

@JsonSerializable()
class MenuModel {
  final int id;
  final String title;
  final String icon;
  final String? route;
  final List<String> roles;
  final List<MenuModel> children;

  MenuModel({
    required this.id,
    required this.title,
    required this.icon,
    this.route,
    required this.roles,
    required this.children,
  });

  factory MenuModel.fromJson(Map<String, dynamic> json) => _$MenuModelFromJson(json);
  Map<String, dynamic> toJson() => _$MenuModelToJson(this);
}

执行命令生成序列化代码:

flutter pub run build_runner build

3. 角色权限过滤逻辑

写递归方法过滤当前角色可访问的菜单(含子菜单):

List<MenuModel> filterMenuByRole(List<MenuModel> allMenus, String currentRole) {
  return allMenus.where((menu) {
    if (!menu.roles.contains(currentRole)) return false;
    // 递归过滤子菜单
    menu.children = filterMenuByRole(menu.children, currentRole);
    return true;
  }).toList();
}

4. 适配插件渲染多级菜单

以你熟悉的multilevel_drawer为例,将过滤后的菜单转为插件所需的Item格式:

// 辅助方法:字符串图标转IconData
IconData getIcon(String iconName) {
  switch(iconName) {
    case 'home': return Icons.home;
    case 'settings': return Icons.settings;
    case 'person': return Icons.person;
    default: return Icons.menu;
  }
}

// 转成MultiLevelDrawerItem格式
List<MultiLevelDrawerItem> convertToDrawerItems(List<MenuModel> filteredMenus) {
  return filteredMenus.map((menu) {
    return MultiLevelDrawerItem(
      label: Text(menu.title),
      icon: Icon(getIcon(menu.icon)),
      subItems: menu.children.isNotEmpty 
          ? convertToDrawerItems(menu.children)
          : null,
      onTap: () {
        if (menu.route != null) {
          Navigator.pushNamed(context, menu.route!);
        }
      },
    );
  }).toList();
}

// 渲染抽屉
MultiLevelDrawer(
  backgroundColor: Colors.white,
  items: convertToDrawerItems(filteredMenus),
)

可用插件推荐

  • multilevel_drawer: 你已熟悉的插件,适配成本低,只需转换数据格式即可复用。
  • expandable: 非抽屉专属,但可配合原生Drawer组件构建可展开的多级列表,灵活性极高。
  • flutter_slidable_drawer: 支持多级菜单嵌套,自定义样式能力强,适合复杂菜单场景。

内容的提问来源于stack exchange,提问作者Subhadip Saha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 11:15:29