Vue3 jsx 语法中使用 v-slots 插槽 和 component动态组件

jsx语法中使用v-slots插槽和动态组件

1.原template 语法中使用 slot 插槽 通过 #title#icon 方式实现
2.动态组件通过component 方式实现

<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

    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递归遍历循环渲染的菜单

<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>

完整的项目代码地址可参考:https://gitee.com/ZHANG_6666/crm-template/blob/develop/src/components/Menu/Menu.vue
如果当前脚手架不支持 jsx语法的编译 需要安装支持 jsx语法的包

npm i @vitejs/plugin-vue-jsx -s

猜你喜欢

转载自blog.csdn.net/weixin_43835425/article/details/130673990