在Vue3 jsx 语法中使用 v-slots 插槽 和 component动态组件,实现一个递归遍历循环渲染的多层级菜单

前言

相信大家在使用vue3开发项目过程中肯定用到过 slots 插槽和 component 动态组件来封装一些业务组件吧,但大多数情况下都是在template 模板语法中去使用的。下面给大家分享一下我个人在项目开发过程中在vue3 jsx语法中去使用 v-slotscomponent 去封装一个递归循环的管理系统多层级菜单

首先看看在 template 模板语法中 slots 和component 是如何使用的

1.原template语法中使用 slot 插槽是通过 #title#icon 方式实现

2.动态组件通过component 方式实现

javascript 复制代码
<template>
  <a-menu>
    <a-sub-menu key="sub1" @titleClick="titleClick">
      <template #icon>
         <component :is="QqOutlined "></component >
      </template>
      <template #title>Navigation One</template>
      <a-menu-item-group key="g1">
        <template #icon>
          <component :is="QqOutlined "></component >
        </template>
        <template #title>Item 1</template>
        <a-menu-item key="1">Option 1</a-menu-item>
        <a-menu-item key="2">Option 2</a-menu-item>
      </a-menu-item-group>
      <a-menu-item-group key="g2" title="Item 2">
        <a-menu-item key="3">Option 3</a-menu-item>
        <a-menu-item key="4">Option 4</a-menu-item>
      </a-menu-item-group>
    </a-sub-menu>
  </a-menu>
</template>

而在jsx语法中插槽和动态组件的使用方法则有很大的不同

1.使用 v-slots 接收插槽参数 default 为默认插槽titleicon为ui组件的作用域插槽

2.动态的实现需要使用 hresolveComponent 这两个组合式api

javascript 复制代码
   const slot = {
       title: () => <span> {menu.meta.title}</span>,
       icon: () => (
         <span>{menu.meta.icon ? h(resolveComponent(menu.meta.icon)) : ""} </span>
       ),
     };
     <a-menu
       mode="inline"
       theme="dark"
       forceSubMenuRender={true}
     >
     <a-sub-menu key={menu.name} v-slots={slot}>
        <a-menu-item key={menu.name}>
           菜单内容
       </a-menu-item>
       </a-sub-menu>
     </a-menu>

完整的代码deom,实现一个menu递归遍历循环渲染的菜单

javascript 复制代码
<script>
import { useStore } from "vuex";
import { useRoute } from "vue-router";
import { computed, ref, watch, h, resolveComponent, defineComponent } from "vue";
export default defineComponent({
  setup() {
    const store = useStore();
    const route = useRoute();
    //当前选中项
    const selectedKeys = ref([route.name]);
    //当前展开项
    const openKeys = ref([route.meta.partentName || ""]);
    const menuTrees = computed(() => store.state.permission.addRouters);
    watch(route, (n, o) => {
      selectedKeys.value = [n.name];
    });

    // 生成 subMenu 菜单
    const renderSubMenu = (menu) => {
      const menuItem = [];
      menu.children.forEach((item) => menuItem.push(renderMenu(item)));
      const slot = {
        title: () => <span> {menu.meta.title}</span>,
        icon: () => (
          <span>{menu.meta.icon ? h(resolveComponent(menu.meta.icon)) : ""} </span>
        ),
      };
      return (
        <a-sub-menu key={menu.name} v-slots={slot}>
          {menuItem}
        </a-sub-menu>
      );
    };
    // 生成  menu-item 菜单
    const renderMenuItem = (menu) => {
      const slot = {
        icon: () => (
          <span>{menu.meta.icon ? h(resolveComponent(menu.meta.icon)) : ""} </span>
        ),
      };
      return (
        <a-menu-item key={menu.name} v-slots={slot}>
          <router-link to={menu.path}>{menu.meta.title}</router-link>
        </a-menu-item>
      );
    };

    const renderMenu = (menu) => {
      return menu.children ? renderSubMenu(menu) : renderMenuItem(menu);
    };

    const menuList = menuTrees.value.map((menu) => {
      return renderMenu(menu);
    });
    return () => (
      <a-menu
        mode="inline"
        theme="dark"
        forceSubMenuRender={true}
        v-model:selectedKeys={selectedKeys.value}
        v-model:openKeys={openKeys.value}
      >
        {menuList}
      </a-menu>
    );
  },
});
</script>

效果图:

如果当前脚手架不支持 jsx语法的编译 需要安装支持 jsx语法的包
javascript 复制代码
npm i @vitejs/plugin-vue-jsx -s

完整的项目代码地址可参考:gitee.com/ZHANG_6666/...

相关推荐
毕设十刻18 分钟前
基于Vue的鲜花销售系统33n62(程序 + 源码 + 数据库 + 调试部署 + 开发环境配置),配套论文文档字数达万字以上,文末可获取,系统界面展示置于文末
前端·数据库·vue.js
IT_陈寒24 分钟前
Spring Boot 3.2震撼发布:5个必知的新特性让你开发效率提升50%
前端·人工智能·后端
San30.26 分钟前
JavaScript 深度解析:从 map 陷阱到字符串奥秘
开发语言·javascript·ecmascript
初遇你时动了情30 分钟前
前端使用TensorFlow.js reactjs调用本地模型 实现图像、文本、音频/声音、视频相关识别
前端·javascript·tensorflow
广州华水科技36 分钟前
单北斗GNSS变形监测系统安装与应用解析,提升位移监测精度
前端
J***Q29239 分钟前
前端微前端框架原理,qiankun源码分析
前端·前端框架
十一.36639 分钟前
66-69 原型对象,toString(),垃圾回收
开发语言·javascript·原型模式
菜鸟‍39 分钟前
【前端学习】React学习【万字总结】
前端·学习·react.js
百***84451 小时前
Webpack、Vite区别知多少?
前端·webpack·node.js
Mintopia1 小时前
零信任架构下的 WebAIGC 服务安全技术升级方向
前端·人工智能·trae