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

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组件的逻辑漏洞:

  1. 找到sidebar附加组件中负责expanded状态切换的_setExpanded方法
  2. 在方法内增加状态判断:如果用户未手动操作过菜单,默认状态取配置中的sidebar.expanded.initial值,不要强制设为展开
  3. 给菜单开合事件绑定状态标记,重绘时优先读取用户手动设置的状态
    这种方案不需要额外绑定全局事件,逻辑更干净。
注意事项
  • 50ms的延迟是为了等插件自身的visibilitychange回调执行完毕,否则你的状态修正会被插件后续的逻辑覆盖
  • 如果后续修改了sidebar.expanded.use的断点值,记得同步修改判断逻辑里的1440阈值,避免判断失效
  • 不需要额外绑定window.resize事件做状态修正,插件本身已经内置了resize监听,额外绑定容易引发状态冲突

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 08:21:51