likes
comments
collection
share

Vue3-递归组件实现动态菜单

作者站长头像
站长
· 阅读数 12

Vue3-递归组件实现动态菜单

一、前言

递归组件是一种特殊的组件,它在自身模板中调用自己。这种组件结构可以很方便地处理具有嵌套层次关系的数据。

常见应用场景

  1. 树状结构展示:递归组件可以用来展示树状结构的数据,比如文件夹结构、评论列表等。通过递归地调用自身,可以很容易地处理多层级嵌套的数据,使得代码更简洁清晰。
  2. 无限滚动列表:当需要实现一个无限滚动列表时,通过递归地渲染每一行数据,可以实现不断加载数据并展示在列表中的效果,提供更好的用户体验。
  3. 导航菜单:对于导航菜单中的多级菜单,通过递归地渲染每个菜单项以及它们的子菜单,可以实现动态生成多级导航菜单的功能。

说明

本文基于 Vue3+AntdesignUI3 环境搭建一个动态菜单来介绍递归组件的使用。

二、实践

实践准备

  • NavigateItem.vue 自定义菜单项组件
  • menu.js 菜单路由文件
  • App.vue 根组件

实践过程

  1. 创建菜单项组件:定义一个用于显示单独菜单项的组件。
  2. 定义菜单数据结构:创建一个适合存储菜单数据的数据结构,包含唯一标识和子菜单项。
  3. 创建递归组件:在组件的template中使用组件自身,用于渲染多级菜单。
  4. 处理递归终止条件:定义递归终止的条件,例如当菜单项没有子菜单项时停止递归。
  5. 渲染菜单:在父组件中使用递归组件并传递菜单数据,来动态生成整个菜单。

NavigateItem.vue

<template>
  // 如果没有子菜单则直接渲染
  <a-menu-item v-if="!('children' in item)" :key="item.path">
    <template #icon><component :is="item.meta.icon" /></template>
    <span>{{ item.meta.title }}</span>
  </a-menu-item>
  // 否则有子菜单
  <a-sub-menu v-else :key="'sub' + item.path">
    <template #icon><component :is="item.meta.icon" /></template>
    <template #title>{{ item.meta.title }}</template>
	// 循环渲染子菜单时要判断子菜单是否又包含子菜单,如果包含则调用自身组件递归渲染
    <template  v-for="child in item.children">
      <NavigateItem v-if="'children' in child" :item="child" />
      <a-menu-item v-else :key="child.path">{{ child.meta.title }} </a-menu-item>
    </template>
  </a-sub-menu>

</template>

<script>
// 这里由于要使用到组件自身,故没有使用setup语法糖
export default {
  name: "NavigateItem",
  props: {
    item: {
      type: Object,
      require: true,
    },
  }
};
</script>

menu.js

import {
  AppstoreOutlined,
  AreaChartOutlined,
  CreditCardOutlined,
  SettingOutlined,
} from "@ant-design/icons-vue";

// 菜单路由
const menuRoute = [
  {
    path: "/",
    name: "root",
    redirect: "/dashboard",
    component: () => import("@/layout/Index.vue"),
    children: [
      {
        path: "/dashboard",
        name: "dashboard",
        component: () => import("@/views/home/Dashboard.vue"),
        meta: {
          title: "工作台",
          icon: AppstoreOutlined,
        },
      },
      {
        path: "/setting",
        name: "setting",
        meta: {
          title: "设置",
          icon: SettingOutlined,
        },
        children: [
          {
            path: "/setting/user",
            name: "user",
            meta: {
              title: "个人设置",
            },
            component: () => import("@/views/setting/UserSetting.vue"),
          },
          {
            path: "/setting/system",
            name: "system",
            meta: {
              title: "系统设置",
            },
            component: () => import("@/views/setting/SysSetting.vue"),
          },
        ],
      },
      {
        path: "/resume",
        name: "resume",
        meta: {
          title: "简历管理",
          icon: CreditCardOutlined,
        },
        children: [
          {
            path: "/add",
            name: "add",
            meta: {
              title: "导入简历",
            },
            component: () => import("@/views/resume/resumeAdd.vue"),
          },
        ],
      },
      {
        path: "/analysis",
        name: "analysis",
        meta: {
          title: "可视化图表分析",
          icon: AreaChartOutlined,
        },
        component: () => import("@/views/analysis/TotalResume.vue"),
      },
    ],
  },
];

export default menuRoute;

App.vue

<template>
  <a-menu mode="inline" theme="dark" @click="handleMenu">
    <NavigateItem v-for="(item,index) in menuRoute[0].children" :item="item" :key="index"/>
  </a-menu>
</template>

<script setup>
// 导入自定义菜单组件
import NavigateItem from "@/components/menu/NavigateItem.vue";
// 导入菜单路由数据
import menuRoute from "@/router/routes/menuRoute.js";
// 导入路由对象
import { useRouter } from "vue-router";
const $router = useRouter();

// 实现点击跳转页面
const handleMenu = (item) => {
  $router.push(item.key);
};
</script>

结果

Vue3-递归组件实现动态菜单

实践结果如图所示,菜单被成功地渲染出来了,图标,文字,点击跳转一点毛病没有。

需要注意的是:递归组件需要在组件内部将name属性设置为自身方可实现递归调用。

三、总结

本篇文章介绍了什么是递归组件、递归组件如何定义并使用以及递归组件在动态菜单中地使用场景。

注意事项:

  1. 确保递归终止条件正确设置,以避免无限递归导致页面崩溃。
  2. 谨慎处理菜单数据的层级关系,确保数据结构符合递归组件的要求。
  3. 使用Vue的key属性标识每个菜单项,以便在数据变化时减少不必要的渲染。
  4. 注意性能优化,可以利用Vue 3的优化特性如<template v-for>和动态组件等进行性能优化。
  5. 对于大型的动态菜单,考虑使用虚拟滚动(virtual scroll)等技术来提高性能。

总之,递归组件是一种强大的工具,可以简化处理多级嵌套数据的场景,但在使用时需要注意正确设置递归终止条件和处理数据层级关系,同时优化性能和用户体验。