如何基于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
相关产品推荐
相关产品推荐

