jQuery mmenu 完整教程

jQuery mmenu 是一个非常流行且功能强大的移动端菜单插件,它能够轻松将一个简单的 HTML 列表转换成一个功能丰富的、可定制的、支持触摸滑动和响应式的侧边栏菜单。

jquery mmenu 教程
(图片来源网络,侵删)

为什么选择 mmenu?

  • 移动优先: 专为触摸设备优化,滑动流畅。
  • 高度可定制: 提供了海量的配置选项,可以改变菜单的方方面面。
  • 主题丰富: 内置多种预设主题,也可以自定义 CSS。
  • 功能强大: 支持页内菜单、悬停子菜单、搜索栏、计数器等。
  • 易于使用: API 简单,文档清晰。

准备工作

你需要引入 mmenu 的核心文件。

  1. 从官网下载 访问 mmenu.js 官网,下载最新版,下载包里会包含 dist 文件夹。

  2. 使用 CDN (推荐) 最简单的方式是使用 CDN,无需下载。

    <!-- jQuery (mmenu 依赖 jQuery) -->
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <!-- mmenu CSS -->
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mmenujs/core/dist/mmenu.css" />
    <!-- mmenu JS -->
    <script src="https://cdn.jsdelivr.net/npm/@mmenujs/core/dist/mmenu.js"></script>

第一个 mmenu 菜单 (Hello World)

让我们创建一个最基础的侧边栏菜单。

jquery mmenu 教程
(图片来源网络,侵删)

HTML 结构

mmenu 的核心是一个无序列表 (<ul>),为了可访问性,最好给它一个 id

<nav id="my-menu">
  <ul>
    <li><a href="/">首页</a></li>
    <li><a href="/about.html">关于我们</a></li>
    <li><a href="/services.html">服务</a></li>
    <li><a href="/contact.html">联系我们</a></li>
  </ul>
</nav>
<!-- 一个用于触发菜单的按钮 -->
<a href="#my-menu" class="mmenu-button">
  <span></span>
  <span></span>
  <span></span>
</a>

初始化 mmenu

</body> 标签前,编写 jQuery 代码来初始化菜单。

jquery mmenu 教程
(图片来源网络,侵删)
<script>
  $(document).ready(function() {
    $("#my-menu").mmenu();
  });
</script>

CSS 样式 (可选但推荐)

默认的菜单样式可能很朴素,你可以添加一些 CSS 来美化你的触发按钮。

/* 为菜单按钮添加一些基本样式 */
.mmenu-button {
  display: block; /* 或 inline-block */
  width: 40px;
  height: 40px;
  background: #333;
  position: relative;
}
.mmenu-button span {
  display: block;
  position: absolute;
  height: 5px;
  width: 100%;
  background: white;
  border-radius: 3px;
  opacity: 1;
  left: 0;
  transform: rotate(0deg);
  transition: .25s ease-in-out;
}
.mmenu-button span:nth-child(1) {
  top: 8px;
}
.mmenu-button span:nth-child(2) {
  top: 17px;
}
.mmenu-button span:nth-child(3) {
  top: 26px;
}

打开你的 HTML 文件,点击那个三道杠按钮,一个漂亮的侧边栏菜单就出现了!


核心配置与选项

mmenu 的强大之处在于其配置选项,你可以在初始化时传入一个配置对象。

$("#my-menu").mmenu({
  // 在这里写你的配置
});

常用配置选项:

选项 类型 默认值 描述
slidingSubmenus 布尔值 true 子菜单是水平滑动 (false) 还是垂直下滑 (true)。强烈建议设为 false,体验更好。
offCanvas 布尔值 true 是否启用“画布外”模式,即菜单从屏幕边缘滑入。
position 字符串 "left" 菜单的位置,可选值: "left", "right", "top", "bottom"
theme 字符串 "white" 菜单的主题颜色,内置: "white", "dark", "black",你也可以自定义。
navbar 布尔值/对象 true 是否显示菜单顶部的导航栏,可以设置为 false 或一个配置对象来自定义。
counters 布尔值 false 是否在菜单项旁显示子菜单项的数量。
searchfield 布尔值 false 是否在菜单顶部添加一个搜索框。

示例:应用常用配置

$("#my-menu").mmenu({
  slidingSubmenus: false, // 子菜单水平滑动
  offCanvas: {
    position: "right", // 从右侧滑出
    zposition: "front" // 菜单在页面前面
  },
  navbar: { "我的菜单" // 自定义导航栏标题
  },
  searchfield: true // 启用搜索框
});

实战示例:带计数器和悬停子菜单的菜单

这是一个更贴近实际应用的例子。

HTML 结构

我们需要一个有子菜单的结构,并添加 data-count 属性来显示计数器。

<nav id="my-menu">
  <ul>
    <li><a href="/">首页</a></li>
    <li><a href="/products.html">产品</a></li>
    <li>
      <a href="/services.html">
        服务
        <span class="mm-counter">3</span> <!-- 手动添加计数器 -->
      </a>
      <ul>
        <li><a href="/web-design.html">网页设计</a></li>
        <li><a href="/logo-design.html">Logo 设计</a></li>
        <li><a href="/seo.html">搜索引擎优化</a></li>
      </ul>
    </li>
    <li><a href="/contact.html">联系我们</a></li>
  </ul>
</nav>

JavaScript 初始化

我们将配置计数器和悬停效果。

$(document).ready(function() {
  var API = $("#my-menu").mmenu({
    // 子菜单使用悬停效果 (需要配合 CSS)
    // 注意:这个配置需要 mmenu-extensions/hover-panels 插件
    // 简单起见,我们用 CSS 实现类似效果
    navbars: [
      {
        position: "top",
        content: [
          "prev", // 返回按钮
          "title", // 页面标题
          "close" // 关闭按钮
        ]
      }
    ],
    // 启用计数器
    counters: true
  });
  var navigator = API.API.getNavigator();
  var drawer = API.API.getDrawer();
  // 绑定事件:当页面变化时,更新导航栏标题
  navigator.bind("open:finish", function() {
    drawer.setPage($(this).attr("href"));
  });
});

CSS for Hover Panels

要实现鼠标悬停显示子菜单(桌面端),可以添加以下 CSS:

/* 仅在桌面端显示悬停效果 */
@media (min-width: 768px) {
  .mm-panels .mm-panel {
    width: 300px; /* 设置子面板宽度 */
  }
  /* 确保父级菜单项可以悬停 */
  .mm-listview > li > a:not(.mm-next) {
    position: relative;
  }
  /* 当鼠标移到父级链接上时,显示子面板 */
  .mm-listview > li > a:not(.mm-next):hover ~ .mm-panel {
    display: block;
  }
  /* 默认隐藏子面板 */
  .mm-listview > li > .mm-panel {
    display: none;
    position: absolute;
    left: 100%;
    top: 0;
    z-index: 2;
  }
}

高级功能与事件处理

获取并控制菜单实例

mmenu() 返回一个包含 API 和其他有用信息的对象。

var menu = $("#my-menu").mmenu();
// 获取 API 对象
var API = menu.API;
// 打开菜单
API.open();
// 关闭菜单
API.close();
// 切换菜单的打开/关闭状态
API.toggle();

监听菜单事件

你可以监听菜单的各种事件来执行自定义操作,例如在菜单打开/关闭时给 body 添加/移除类,以防止页面滚动。

var menu = $("#my-menu").mmenu();
var API = menu.API;
// 监听菜单打开事件
API.bind("open:start", function() {
  console.log("菜单开始打开");
  $("body").addClass("is-menu-opened"); // 添加类,防止页面滚动
});
// 监听菜单关闭事件
API.bind("close:finish", function() {
  console.log("菜单已经关闭");
  $("body").removeClass("is-menu-opened"); // 移除类,恢复页面滚动
});

CSS 防止页面滚动:

/* 当菜单打开时,body 的样式 */
body.is-menu-opened {
  overflow: hidden; /* 隐藏溢出,防止滚动 */
  position: fixed; /* 固定位置 */
  width: 100%;
}

最佳实践与注意事项

  1. 性能优化:

    • 按需引入: mmenu 提供了很多扩展(如搜索、计数器、图标等),不要一次性引入所有 JS/CSS,只引入你需要的。
    • 使用 CDN: CDN 能提供更快的加载速度。
  2. 可访问性 (Accessibility):

    • 使用 <nav> 标签包裹菜单。
    • 为触发按钮添加 aria-labelaria-expanded 属性,以便屏幕阅读器理解。
    • mmenu 本身对可访问性支持良好,遵循其文档即可。
  3. 响应式设计:

    • 在大屏幕上,你可能希望隐藏 mmenu 按钮,并使用一个水平导航栏。
    • 使用 CSS 媒体查询来控制菜单按钮和导航栏的显示。
    /* 默认显示菜单按钮,隐藏水平导航 */
    .desktop-nav { display: none; }
    .mmenu-button { display: block; }
    /* 在大屏幕上,隐藏菜单按钮,显示水平导航 */
    @media (min-width: 992px) {
      .desktop-nav { display: block; }
      .mmenu-button { display: none; }
      /* 并且可以在这里初始化一个水平菜单,或者直接显示普通的 <nav> */
    }
  4. 自定义主题:

    • 不要直接修改 mmenu 的源 CSS 文件,通过配置选项 theme 或者在你的主 CSS 文件中使用更具体的选择器(如 #my-menu .mm-listview)来覆盖样式。

完整代码示例

<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF--8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">jQuery mmenu 教程示例</title>
  <style>
    /* 基础样式 */
    body { font-family: sans-serif; margin: 0; }
    .content { padding: 20px; }
    .mmenu-button {
      display: block; width: 40px; height: 40px; background: #333; position: fixed; top: 10px; left: 10px; z-index: 1000;
    }
    .mmenu-button span {
      display: block; position: absolute; height: 5px; width: 100%; background: white; border-radius: 3px; left: 0;
      transition: .25s ease-in-out;
    }
    .mmenu-button span:nth-child(1) { top: 8px; }
    .mmenu-button span:nth-child(2) { top: 17px; }
    .mmenu-button span:nth-child(3) { top: 26px; }
    body.is-menu-opened { overflow: hidden; }
  </style>
  <!-- mmenu CSS -->
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mmenujs/core/dist/mmenu.css" />
</head>
<body>
  <!-- 触发按钮 -->
  <a href="#my-menu" class="mmenu-button">
    <span></span>
    <span></span>
    <span></span>
  </a>
  <!-- 页面内容 -->
  <div class="content">
    <h1>欢迎使用 mmenu</h1>
    <p>点击左上角的菜单按钮来体验侧边栏菜单。</p>
  </div>
  <!-- mmenu HTML 结构 -->
  <nav id="my-menu">
    <ul>
      <li><a href="/">首页</a></li>
      <li><a href="/about.html">关于我们</a></li>
      <li>
        <a href="/services.html">
          服务
          <span class="mm-counter">3</span>
        </a>
        <ul>
          <li><a href="/web-design.html">网页设计</a></li>
          <li><a href="/logo-design.html">Logo 设计</a></li>
          <li><a href="/seo.html">搜索引擎优化</a></li>
        </ul>
      </li>
      <li><a href="/contact.html">联系我们</a></li>
    </ul>
  </nav>
  <!-- jQuery -->
  <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
  <!-- mmenu JS -->
  <script src="https://cdn.jsdelivr.net/npm/@mmenujs/core/dist/mmenu.js"></script>
  <script>
    $(document).ready(function() {
      // 初始化 mmenu
      var menu = $("#my-menu").mmenu({
        slidingSubmenus: false,
        offCanvas: {
          position: "left"
        },
        navbar: {
          title: "主导航"
        },
        counters: true
      });
      // 获取 API
      var API = menu.API;
      // 绑定事件:打开菜单时,给 body 添加类
      API.bind("open:start", function() {
        $("body").addClass("is-menu-opened");
      });
      // 绑定事件:关闭菜单时,移除 body 的类
      API.bind("close:finish", function() {
        $("body").removeClass("is-menu-opened");
      });
      // 可选:当点击菜单项后,关闭菜单
      API.bind("closed", function() {
        // 这里可以添加页面跳转逻辑
      });
    });
  </script>
</body>
</html>

将以上代码保存为 .html 文件,用浏览器打开即可看到一个功能完整的 mmenu 菜单。

希望这份教程能帮助你快速上手 jQuery mmenu!