返回

巧用递归组件:Vue3 + JSX 打造无限级菜单,惊艳你的项目

前端

随着 Vue3 的兴起和 JSX 语法的引入,前端开发迎来了新的变革。在此背景下,我们可以借助递归组件的强大功能,实现更加灵活和优雅的无限级菜单。本文将从实际需求出发,深入剖析如何使用 Vue3 + JSX 构建一个令人惊艳的无限级菜单,为你的项目注入新的活力。

递归组件的巧妙运用

递归组件是指能够调用自身的一个组件。在无限级菜单的场景中,我们希望根据路由信息动态生成菜单项,而每个菜单项又可以包含子菜单,形成一个树状结构。

为了实现这一目标,我们可以使用一个递归组件 MenuItem,它负责渲染单个菜单项及其子菜单:

<script lang="ts">
import { h, defineComponent } from 'vue';

const MenuItem = defineComponent({
  props: {
    item: {
      type: Object,
      required: true,
    },
  },
  setup(props) {
    const hasChildren = props.item.children && props.item.children.length > 0;

    return () => {
      return h('li', {}, [
        h('a', { href: props.item.path }, props.item.name),
        hasChildren ? h(MenuItem, { item: props.item.children }) : null,
      ]);
    };
  },
});

export default MenuItem;
</script>

MenuItem 组件中,我们根据 item 属性动态渲染菜单项名称和链接。如果 item 拥有子菜单,则递归调用 MenuItem 组件继续渲染子菜单。

主菜单组件的搭建

接下来,我们需要一个主菜单组件 Menu,负责协调多个 MenuItem 组件,形成完整的菜单结构:

<script lang="ts">
import { h, defineComponent } from 'vue';
import MenuItem from './MenuItem.vue';

const Menu = defineComponent({
  setup() {
    const menuItems = [
      {
        name: 'Home',
        path: '/',
      },
      {
        name: 'About',
        path: '/about',
      },
      {
        name: 'Blog',
        path: '/blog',
        children: [
          {
            name: 'All Posts',
            path: '/blog',
          },
          {
            name: 'Categories',
            path: '/blog/categories',
          },
        ],
      },
    ];

    return () => {
      return h('ul', {}, menuItems.map(item => h(MenuItem, { item })));
    };
  },
});

export default Menu;
</script>

Menu 组件中,我们定义了菜单项数组 menuItems,并使用 map 方法将每个菜单项映射为一个 MenuItem 组件。

集成到项目中

最后,我们将 Menu 组件集成到 Vue 实例中,完成无限级菜单的渲染:

<script lang="ts">
import { createApp } from 'vue';
import Menu from './Menu.vue';

createApp({
  components: {
    Menu,
  },
}).mount('#app');
</script>

结语

通过本文的深入剖析,你已经掌握了使用 Vue3 + JSX 和递归组件构建无限级菜单的秘诀。这种方法不仅灵活优雅,而且能够完美适应路由变化,为你的前端项目注入全新的活力。快去尝试一下,让你的菜单脱颖而出,成为项目的亮点吧!