mmenu Sidebar插件初始关闭状态失效 切回标签页菜单自动打开
问题根因
该问题是mmenu sidebar附加组件的原生逻辑bug:页面触发visibilitychange事件(切换标签页、最小化窗口后恢复)时,插件会重新执行sidebar视口适配逻辑,但逻辑中缺失两个关键判断:
- 未读取初始化时传入的
sidebar.expanded.initial默认状态配置 - 未持久化存储用户手动打开/关闭菜单的操作状态,重绘时直接将满足expanded视口阈值的菜单默认设为展开状态
你之前写的强制关闭逻辑缺陷在于没有区分「插件bug导致的意外展开」和「用户主动打开菜单后切走页面」两种场景,会直接覆盖用户的正常操作。
修复方案
方案1:状态标记修复(无侵入,最小改动)
核心逻辑是单独维护两个状态变量:一个是初始化配置的默认菜单状态,一个是用户手动操作后的菜单状态,页面恢复可见时根据状态判断是否需要修正菜单,而非无脑执行关闭。
实现代码:
const menu = new Mmenu( "#menu", { counters: { add: true, }, iconPanels: { add: true, visible: "first", }, navbar: { title: "...", }, navbars: [ { position: "top", content: ["searchfield"], }, { position: "top", }, ], setSelected: { hover: true, parent: true, }, sidebar: { collapsed: { use: 768, }, expanded: { use: 1440, initial: "closed", }, }, theme: "white", }, { offCanvas: { page: { selector: "#page", }, }, searchfield: { cancel: true, clear: true, }, } ); const api = menu.API; // 存储配置的默认展开状态 const DEFAULT_EXPANDED_STATE = "closed"; // 存储用户手动操作后的菜单状态,未操作时为null let userSetState = null; // 监听菜单开合事件,同步用户操作状态 api.bind("open:finish", () => { userSetState = "open"; }); api.bind("close:finish", () => { userSetState = "closed"; }); document.addEventListener("visibilitychange", () => { if (document.visibilityState !== "visible") return; // 延迟执行,等待插件自身的visibilitychange回调执行完成后再覆盖状态 setTimeout(() => { // 仅在视口满足expanded断点时处理 if (window.innerWidth < 1440) return; // 优先使用用户手动设置的状态,未操作过则使用默认配置状态 const targetState = userSetState ?? DEFAULT_EXPANDED_STATE; targetState === "closed" ? api.close() : api.open(); }, 50); });
该方案不会干扰正常交互:如果用户切页前主动打开了菜单,返回页面时菜单会保持打开状态;如果用户未做过手动操作,返回页面时菜单会保持配置的默认关闭状态,不会被插件逻辑错误展开。
方案2:源码层面修复(一劳永逸)
如果可以修改本地引入的mmenu源码,可以直接修正sidebar组件的逻辑漏洞:
- 找到sidebar附加组件中负责expanded状态切换的
_setExpanded方法 - 在方法内增加状态判断:如果用户未手动操作过菜单,默认状态取配置中的
sidebar.expanded.initial值,不要强制设为展开 - 给菜单开合事件绑定状态标记,重绘时优先读取用户手动设置的状态
这种方案不需要额外绑定全局事件,逻辑更干净。
注意事项
- 50ms的延迟是为了等插件自身的
visibilitychange回调执行完毕,否则你的状态修正会被插件后续的逻辑覆盖 - 如果后续修改了
sidebar.expanded.use的断点值,记得同步修改判断逻辑里的1440阈值,避免判断失效 - 不需要额外绑定
window.resize事件做状态修正,插件本身已经内置了resize监听,额外绑定容易引发状态冲突
内容的提问来源于stack exchange,提问作者kollew
相关产品推荐
相关产品推荐

