后端【免费下载链接】flask-adminSimple and extensible administrative interface framework for Flask项目地址https://gitcode.com/gh_mirrors/fl/flask-admin点击查看免费下载本文围绕 flask-admin 仓库内置的第三方组件multi-level-dropdowns-bootstrap展开讲解如何在不修改 Bootstrap 4 官方 CSS/JS 的前提下让下拉菜单支持无限层级展开。文章既覆盖组件的完整用法基础引入、Hover 触发、事件处理也结合 flask-admin 源码说明其在后台导航菜单中的真实集成方式与工作原理读完即可在自己的 Bootstrap 4 项目中复刻同款多级菜单。背景Bootstrap 4 原生下拉为何做不到多级Bootstrap 4 的官方下拉组件dropdown.js在设计上只支持“一层下拉”点击/悬停[data-toggledropdown]元素后dropdown.js只会切换当前菜单的show类当二级菜单里再嵌套一个.dropdown时官方组件既不会在点击时阻止事件冒泡也不会在关闭时区分“子菜单是否仍处于打开状态”结果就是子菜单一点开父菜单就被关闭深层菜单永远无法稳定显示。multi-level-dropdowns-bootstrap正是针对这一缺口设计的 hack它复用 Bootstrap 官方的dropdown()方法、事件与数据结构只通过一层轻量包装就能实现“无限级”下拉且不引入任何额外 CSS 类来覆盖官方样式——正如其 README 所说“Using official HTML without adding extra CSS styles and classes, its just like native support”。该组件对应的核心文件位于仓库 flask_admin/static/vendor/multi-level-dropdowns-bootstrap/ 目录文件作用bootstrap4-dropdown-ml-hack.js核心多级下拉 hack点击触发bootstrap4-dropdown-ml-hack-hover.js带 Hover 触发版本包含 hack 鼠标悬停逻辑bootstrap4-dropdown-ml-hack-hover.css配合 Hover 使用的间距修正样式README.md官方使用说明本文分析主体基础用法一行script开启多级下拉根据 README 的 “Base” 部分多级下拉的开启方式极其简单在 jQuery 与 Bootstrap 的 JS 文件之后引入 hack 脚本即可script srchttps://raw.githubusercontent.com/dallaslu/bootstrap-4-multi-level-dropdown/master/bootstrap4-dropdown-ml-hack.js/script注意事项加载顺序必须为jquery → bootstrap含 dropdown.js→ 本 hack 脚本因为 hack 内部会读取并包装$.fn.dropdown依赖官方组件已就绪引入后无需修改任何 HTML 结构官方文档 getbootstrap.com/docs/4.4/components/dropdowns 中列出的所有功能不受影响——CSS 类、JS 方法、事件与选项均可照常使用在 flask-admin 中该脚本并非由用户手工引入而是由后台基础模板统一加载详见下文“flask-admin 的集成方式”。原理剖析hack 到底改了什么阅读仓库内的 bootstrap4-dropdown-ml-hack.js 源码可以发现它的全部逻辑只有 26 行核心是“包装官方方法 接管事件”$.fn.dropdown (function() { var $bsDropdown $.fn.dropdown; // 1. 保存官方 $.fn.dropdown return function(config) { if (typeof config string config toggle) { // 2. 拦截 toggle 调用 $(.has-child-dropdown-show).removeClass(has-child-dropdown-show); $(this).closest(.dropdown).parents(.dropdown).addClass(has-child-dropdown-show); } var ret $bsDropdown.call($(this), config); // 3. 调用官方方法完成实际开关 $(this).off(click.bs.dropdown); // 4. 关闭官方内置的 click 绑定防止重复 toggle return ret; } })(); $(function() { $(.dropdown [data-toggledropdown]).on(click, function(e) { $(this).dropdown(toggle); e.stopPropagation(); // 5. 阻止冒泡避免事件传给父级 dropdown }); $(.dropdown).on(hide.bs.dropdown, function(e) { if ($(this).is(.has-child-dropdown-show)) { // 6. 子菜单打开时阻止父菜单被隐藏 $(this).removeClass(has-child-dropdown-show); e.preventDefault(); } e.stopPropagation(); // 7. 多级模式下不再向上传播 hide 事件 }); });逐段拆解其工作机制包装$.fn.dropdown先把官方实现保存为$bsDropdown再返回新函数。这样外部调用$(...).dropdown(toggle)时仍会执行官方逻辑hack 只是在其前后追加行为。标记祖先菜单触发toggle时先清除全局的has-child-dropdown-show标记再给当前.dropdown的所有祖先.dropdown加上该标记用于记录“哪些父菜单下有正在打开的子菜单”。移除官方 click 绑定Bootstrap 官方dropdown.js会给[data-toggledropdown]绑定click.bs.dropdown内部会再次调用toggle()hack 用$(this).off(click.bs.dropdown)将其关闭避免一次点击触发两次开关导致菜单闪动。点击事件自行接管在 document ready 后统一为所有.dropdown [data-toggledropdown]绑定 click显式调用dropdown(toggle)并e.stopPropagation()——这是多级菜单最关键的一步点击子菜单按钮时事件不会冒泡到父级 dropdown 的处理器父菜单因此不会被意外关闭。拦截hide.bs.dropdown当某个 dropdown 触发隐藏事件时如果它带有has-child-dropdown-show标记说明它的子菜单还开着就preventDefault()阻止其关闭并移除标记同时stopPropagation()阻止隐藏事件继续向上传播保证深层菜单关闭时不会连坐关闭上层菜单。这套设计保证了两个核心体验点开深层子菜单时父级保持打开关闭深层子菜单时父级不受影响。Hover 触发鼠标悬停即展开README 的 “Hover” 部分提供了两种实现方式。方式一手动加样式 事件先加一行 CSS把菜单与触发元素之间的间距归零避免鼠标从按钮移向菜单时触发mouseleave而被误关.dropdown-hover-all .dropdown-menu, .dropdown-hover .dropdown-menu { margin:0 }再为指定容器绑定mouseenter/mouseleave事件用dropdown(toggle)README 建议使用toggle以获得最佳体验控制开关$(.dropdown-hover).on(mouseenter,function() { if(!$(this).hasClass(show)){ $([data-toggledropdown], this).dropdown(toggle); } }); $(.dropdown-hover).on(mouseleave,function() { if($(this).hasClass(show)){ $([data-toggledropdown], this).dropdown(toggle); } }); $(.dropdown-hover-all).on(mouseenter, .dropdown, function() { if(!$(this).hasClass(show)){ $([data-toggledropdown], this).dropdown(toggle); } }); $(.dropdown-hover-all).on(mouseleave, .dropdown, function() { if($(this).hasClass(show)){ $([data-toggledropdown], this).dropdown(toggle); } });两类选择器的区别.dropdown-hover针对单个dropdown 元素只监听其自身的鼠标进出.dropdown-hover-all针对容器内所有.dropdown利用事件委托on(mouseenter, .dropdown, ...)一次绑定、全局生效适合整条导航栏整体启用 Hover。方式二直接引入配套文件如果不想手写事件仓库已经提供了现成的组合文件README 给出的完整用法如下link relstylesheet hrefhttps://raw.githubusercontent.com/dallaslu/bootstrap-4-multi-level-dropdown/master/bootstrap4-dropdown-ml-hack-hover.css / ... div classdropdown-hover-all !-- .dropdown elements -- /div div classdropdown dropdown-hover !-- toggle and menu elements -- /div ... script srchttps://raw.githubusercontent.com/dallaslu/bootstrap-4-multi-level-dropdown/master/bootstrap4-dropdown-ml-hack-hover.js/script对照仓库文件可以确认bootstrap4-dropdown-ml-hack-hover.css 内容与 README 中的样式完全一致margin:0一条规则bootstrap4-dropdown-ml-hack-hover.js 前 26 行与bootstrap4-dropdown-ml-hack.js完全相同其后追加了.dropdown-hover/.dropdown-hover-all的鼠标事件绑定。因此若只需点击触发引入bootstrap4-dropdown-ml-hack.js一个文件即可需要 Hover 时则换成-hover后缀的 JS CSS 组合。flask-admin 的集成方式后台导航栏的多级菜单flask-admin 使用 Bootstrap 4 渲染整个管理后台界面其左侧顶部导航由Admin.menu()生成的菜单树驱动。为了让分类category可以嵌套为多级下拉仓库直接内置了该 hack 组件。1. 模板层统一加载 hack 脚本所有 Bootstrap 4 后台页面共用的基础模板 flask_admin/templates/bootstrap4/admin/base.html 在tail_js块中按顺序加载脚本见 base.html 第 81-98 行script src{{ admin_static.url(filenamevendor/jquery.min.js, v3.5.1) }} .../script script src{{ admin_static.url(filenamebootstrap/bootstrap4/js/bootstrap.min.js, v4.6.2) }} .../script script src{{ admin_static.url(filenamevendor/bootstrap4/util.js, v4.3.1) }} .../script script src{{ admin_static.url(filenamevendor/bootstrap4/dropdown.js, v4.3.1) }} .../script script src{{ admin_static.url(filenamevendor/multi-level-dropdowns-bootstrap/bootstrap4-dropdown-ml-hack.js) }} .../script可以观察到 flask-admin 在加载顺序上的刻意安排jquery.min.jsv3.5.1与bootstrap.min.jsv4.6.2在前之后是官方util.js与dropdown.jsv4.3.1——dropdown.js是 hack 包装的目标对象必须先就位最后才是bootstrap4-dropdown-ml-hack.js且未启用 Hover 版本即后台菜单默认使用“点击展开”交互。这正好印证了 README 中“Just add js after jquery and bootstrap js files”的要求hack 脚本必须后于官方组件加载。2. 菜单渲染递归生成嵌套.dropdown后台菜单由 flask_admin/templates/bootstrap4/admin/layout.html 中的menu()宏渲染见 layout.html 第 21-83 行。其关键逻辑是递归遇到is_category()的菜单项时渲染一个li classdropdown内部a>{%- if child.is_category() -%} {{ menu(menu_root[child]) }} {% else %} ...渲染普通菜单项... {%- endif -%}最终 DOM 形如li classdropdown a classdropdown-toggle nav-link>class SubMenuCategory(MenuCategory): def __init__(self, *args: str, **kwargs: t.Any) - None: super().__init__(*args, **kwargs) self.class_name dropdown-submenu droprightMenuDividermenu.py 第 186-203 行渲染为dropdown-divider分隔线get_url()返回None用于在菜单中插入视觉分隔。在 layout.html 第 37-41 行 中渲染宏还会依据class_name是否包含dropdown-submenu来决定显示“右箭头”还是“下箭头”图标说明SubMenuCategory的dropright类正是多级菜单“向右弹出”视觉语义的来源。与 Bootstrap 官方功能的兼容性README 特别强调官方文档中列出的所有dropdown 能力均不受 hack 影响可以放心混用CSS 类.dropdown-menu-right、.dropdown-header、.dropdown-divider、.disabled等官方类照常生效JS 方法toggle、show、hide、update等方法仍由官方实现执行hack 只是在toggle前后附加了祖先标记逻辑事件show.bs.dropdown、shown.bs.dropdown、hide.bs.dropdown、hidden.bs.dropdown等官方事件照常触发hack 仅额外监听hide.bs.dropdown做保护性拦截选项如offset、flip、boundary、reference、display等 Popper.js 相关选项不受影响。其设计哲学是“只增加行为、不改写行为”——从 bootstrap4-dropdown-ml-hack.js 源码可以看到hack 全程保留了对官方$bsDropdown的调用未替换官方实现也未新增任何覆盖官方样式的 CSS。兼容性验证与使用建议README 给出的官方 Demo 基于Bootstrap v4.4.1验证可用flask-admin 在 base.html 中同时加载了bootstrap.min.jsv4.6.2与dropdown.jsv4.3.1从源码结构与官方 README 声明可以推断该 hack 与 Bootstrap 4 系列版本均能协同工作点击版 vs Hover 版桌面端管理后台若追求效率可考虑 Hover 版引入-hover后缀的两个文件但需注意 README 中“减少间距以避免误触发 mouseleave”的 CSS 提示移动端触屏场景下点击版更稳妥加载顺序务必确保 hack 脚本在 jQuery 与官方 dropdown 组件之后加载否则包装$.fn.dropdown时会拿到未定义的实现若在 flask-admin 之外的项目中独立使用直接参照上文“基础用法”与“Hover 触发”两节引入仓库 flask_admin/static/vendor/multi-level-dropdowns-bootstrap/ 中的对应文件即可无需依赖 flask-admin 本身。小结multi-level-dropdowns-bootstrap用不到 30 行的轻量 hack为 Bootstrap 4 补上了官方缺失的“无限级下拉”能力且保持了对官方组件的高度兼容。在 flask-admin 中它通过与SubMenuCategory/MenuDivider菜单模型、layout.html递归渲染宏的配合让后台导航得以支持多级分类组织。理解其“包装$.fn.dropdown、接管 click、拦截hide.bs.dropdown”的三段式原理后你既可以直接复用仓库文件也能在遇到类似交互需求时举一反三。赞分享后端【免费下载链接】flask-adminSimple and extensible administrative interface framework for Flask项目地址https://gitcode.com/gh_mirrors/fl/flask-admin点击查看免费下载相关推荐Ant Design Blazor Dropdown 多级菜单实现指南Dropdown 与 SubMenu 联动的级联下拉菜单Ant Design Blazor Dropdown 多级菜单实现指南Dropdown 与 SubMenu 联动的级联下拉菜单 在 Ant Design Bl前端UI组件设计系统Ant Design Dropdown 多级菜单SubMenu实战指南在 React 下拉菜单中实现层级嵌套Ant Design Dropdown 多级菜单SubMenu实战指南在 React 下拉菜单中实现层级嵌套 本篇技术指南以 Ant Design 仓库中UI组件前端设计系统Brython 导航菜单实战指南用 browser.widgets.menu 构建横向导航栏与多级下拉子菜单Brython 导航菜单实战指南用 browser.widgets.menu 构建横向导航栏与多级下拉子菜单 本文是 Brython运行在浏览器中的 Pyt编程语言语言运行时编译器前端上一篇5分钟快速上手Arduino ESP32物联网开发的终极解决方案下一篇dijo视图模式完全指南Day模式和Week模式的数据可视化技巧创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考