uniapp一级菜单和二级菜单

admin 103 0
uniapp中一级菜单通常作为主导航,如底部Tab栏或顶部导航栏,用于核心模块切换(如首页、分类、个人中心),可通过uni-tabbar或自定义组件实现,二级菜单则是一级菜单的子级,用于细分功能,如分类下的商品子类目,可通过uni-popup弹出层、uni-collapse折叠面板或侧边滑出等方式展示,点击一级菜单项触发二级菜单展开,选择后执行相应操作,两者结合可实现层级清晰、交互流畅的导航结构,适配多端场景。

Uniapp 一级菜单与二级菜单实现全攻略:从布局到交互

在移动端应用开发中,菜单作为导航的核心组件,其层级设计和交互体验直接影响用户的使用效率,Uniapp 作为一款跨端开发框架,通过一套代码即可适配 H5、小程序、App 等多端平台,其菜单实现需兼顾多端兼容性与交互流畅性,本文将详细介绍 Uniapp 中一级菜单与二级菜单的实现逻辑,从布局结构到交互细节,助你快速掌握菜单开发技巧。

菜单的基本概念与应用场景

一级菜单与二级菜单的定义

一级菜单是导航的顶层入口,通常水平排列在页面顶部或垂直排列在侧边,直接关联核心功能模块(如"首页"、"分类"、"我的"),二级菜单是一级菜单的子级,点击一级菜单后展开,用于展示更细化的功能分类(如"分类"一级菜单下可能包含"电子产品"、"服装食品"等二级分类)。

常见应用场景

  • 顶部导航栏:电商平台首页的一级菜单(如"商品分类"、"品牌专区"),点击展开二级菜单展示具体分类。
  • 侧边栏导航:管理系统的左侧一级菜单(如"用户管理"、"订单管理"),点击展开二级菜单展示子功能(如"用户列表"、"权限设置")。
  • 底部 Tab 栏:虽然通常作为一级导航,但结合弹出层可实现类似二级菜单的交互(如"更多"按钮点击后弹出二级选项)。
  • 抽屉式菜单:App 中常见的侧滑菜单,一级菜单垂直排列,点击后横向展开二级菜单。

Uniapp 实现一级菜单的核心逻辑

一级菜单的实现相对简单,核心是布局结构 + 数据绑定 + 点击交互,以常见的顶部水平菜单为例,以下是具体步骤:

数据结构设计

一级菜单的数据通常是一个数组,每个元素包含 id(唯一标识)、titleicon(图标,可选)等字段:

data() {
  return {
    firstMenuList: [
      { id: 1, title: '首页', icon: '/static/home.png' },
      { id: 2, title: '分类', icon: '/static/category.png' },
      { id: 3, title: '发现', icon: '/static/find.png' },
      { id: 4, title: '我的', icon: '/static/user.png' }
    ],
    activeFirstId: 1 // 当前激活的一级菜单 ID
  }
}

布局结构实现

使用 <view> 结合 v-for 循环渲染菜单项,通过动态绑定 class 控制激活状态的样式:

<template>
  <view class="first-menu-container">
    <view 
      v-for="item in firstMenuList" 
      :key="item.id"
      class="menu-item"
      :class="{ active: activeFirstId === item.id }"
      @click="handleFirstClick(item.id)"
    >
      <image v-if="item.icon" :src="item.icon" class="menu-icon"></image>
      <text class="menu-title">{{ item.title }}</text>
    </view>
  </view>
</template>

样式设计

通过 CSS 设置菜单的布局、间距、激活状态等样式:

.first-menu-container {
  display: flex;
  background-color: #fff;
  border-bottom: 1px solid #eee;
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
}
.menu-item {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  height: 80rpx;
  font-size: 28rpx;
  color: #333;
  transition: all 0.3s ease;
}
.menu-icon {
  width: 40rpx;
  height: 40rpx;
  margin-bottom: 4rpx;
}
.menu-item.active {
  color: #ff6b6b;
  background-color: #fff5f5;
  font-weight: bold;
}

点击交互处理

通过 @click 事件绑定处理函数,更新激活的菜单 ID:

methods: {
  handleFirstClick(id) {
    this.activeFirstId = id;
    // 可在此处触发页面跳转或数据加载逻辑
    console.log('点击一级菜单 ID:', id);
    // 如果需要跳转到对应页面
    // uni.switchTab({
    //   url: `/pages/tab-${id}/tab-${id}`
    // });
  }
}

Uniapp 实现二级菜单的核心逻辑

二级菜单的核心是一级菜单点击展开/收起 + 二级菜单动态渲染 + 状态管理,以一级菜单"分类"为例,点击后展开二级分类列表:

数据结构设计

在一级菜单数据的基础上,增加 children 字段存储二级菜单数据:

data() {
  return {
    firstMenuList: [
      { id: 1, title: '首页', icon: '/static/home.png' },
      { 
        id: 2, 
        title: '分类', 
        icon: '/static/category.png',
        children: [ // 二级菜单数据
          { id: 21, title: '电子产品', icon: '/static/electronics.png' },
          { id: 22, title: '服装鞋包', icon: '/static/clothing.png' },
          { id: 23, title: '食品生鲜', icon: '/static/food.png' },
          { id: 24, title: '家居家装', icon: '/static/home.png' }
        ]
      },
      { id: 3, title: '发现', icon: '/static/find.png' },
      { id: 4, title: '我的', icon: '/static/user.png' }
    ],
    activeFirstId: 1,
    isSecondMenuShow: false, // 控制二级菜单显示/隐藏
    currentSecondList: [] // 当前显示的二级菜单列表
  }
}

布局结构实现

在一级菜单下方,通过 <view>v-ifv-show 控制二级菜单的显示,并动态渲染二级菜单项:

<template>
  <view class="menu-container">
    <!-- 一级菜单 -->
    <view class="first-menu-container">
      <view 
        v-for="item in firstMenuList" 
        :key="item.id"
        class="menu-item"
        :class="{ active: activeFirstId === item.id }"
        @click="handleFirstClick(item)"
      >
        <image v-if="item.icon" :src="item.icon" class="menu-icon"></image>
        <text class="menu-title">{{ item.title }}</text>
        <text v-if="item.children" class="arrow-icon" :class="{ rotate: isSecondMenuShow }">></text>
      </view>
    </view>
    <!-- 二级菜单 -->
    <view v-if="isSecondMenuShow && currentSecondList.length" class="second-menu-container">
      <view 
        v-for="item in currentSecondList" 
        :key="item.id"
        class="second-menu-item"
        @click="handleSecondClick(item)"
      >
        <image v-if="item.icon" :src="item.icon" class="second-menu-icon"></image>
        <text class="second-menu-title">{{ item.title }}</text>
      </view>
    </view>
  </view>
</template>

交互逻辑实现

methods: {
  handleFirstClick(item) {
    // 如果点击的是有子菜单的项目
    if (item.children) {
      // 如果当前已经展开,则收起
      if (this.isSecondMenuShow && this.activeFirstId === item.id) {
        this.isSecondMenuShow = false;
        this.currentSecondList = [];
      } else {
        // 否则展开新的子菜单
        this.activeFirstId = item.id;
        this.currentSecondList = item.children;
        this.isSecondMenuShow = true;
      }
    } else {
      // 如果点击的是没有子菜单的项目
      this.activeFirstId = item.id;
      this.isSecondMenuShow = false;
      this.currentSecondList = [];

标签: #一级菜单 #二级菜单