前言

vue-pure-admin是一款比较通用的后台框架。

vue-pure-admin

全面使用ESM+Vue3+Vite+Element-Plus+TypeScript编写的一款后台管理系统(兼容移动端),目前斩获11.5k个star。

在这里插入图片描述

界面构成

主题Layout的组成

  • 左边sidebar由Vertical组件定义
  • tab标签栏由layoutHeader组件定义
  • 中间Body由appMain组件定义

图标加载

该项目使用到了多个图标库,iconify是主要的一个。例如导航栏的菜单项目的图标。
sidebarItem.vue:

<el-icon v-show="props.item.meta.icon">
        <component
          :is="
            useRenderIcon(
              onlyOneChild.meta.icon ||
                (props.item.meta && props.item.meta.icon)
            )
          "
        ></component>
</el-icon>

该图标绘制实现在useRenderIcon()中:

/**
 * 支持fontawesome4、5+、iconfont、remixicon、element-plus的icons、自定义svg
 * @param icon 必传 string 图标或者对象
 * @param attrs 可选 iconType 属性
 * @returns Component
 */
export function useRenderIcon(icon: string|Component, attrs?: iconType): Component {
  // iconfont
  const ifReg = /^IF-/;
  // typeof icon === "function" 属于SVG
  if (typeof icon === "object") {
    return icon
  }
  if (typeof icon === "string" && ifReg.test(icon)) {
    // iconfont
    const name = icon.split(ifReg)[1];
    const iconName = name.slice(
      0,
      name.indexOf(" ") == -1 ? name.length : name.indexOf(" ")
    );
    const iconType = name.slice(name.indexOf(" ") + 1, name.length);
    return defineComponent({
      name: "FontIcon",
      render() {
        return h(FontIcon, {
          icon: iconName,
          iconType,
          ...attrs
        });
      }
    });
  } else if (typeof icon === "function") {
    // svg
    return icon;
  } else {
    return defineComponent({
      name: "Icon",
      render() {
        return h(IconifyIconOffline, {
          icon: icon,
          ...attrs
        });
      }
    });
  }
}

原实现只支持icon为字符串,为了方便引用本地资源,我加上了对对象类型的支持。示例:

import settings from "@/assets/svg/settings.svg?component";
...
meta: {
        title: $t("menus.blogMain"),
        i18n: true,
        show: true,
        icon: settings
}

为何点击链接都会打开一个tab页?

看一下tag/index.vue里的实现。每次我们进行路由跳转时,做了两件事情:

  1. useMultiTagsStoreHook().handleTags(“push”, {})
  2. router.push({})
    前者添加一个tab,后者切换一下路由。Tag组件的绘制在components/tag/index.vue中。
    Tab的实现:
<div v-for="(item, index) in multiTags">

<keep-alive>
    <router-link :to="{path: item?.path, query: item?.query}"
    >{{ transformI18n(item.meta.title, item.meta.i18n) }}
    </router-link>
</keep-alive>
</div>

点击每个tab时,调用tagOnClick()方法触发tags标签切换:

function tagOnClick(item) {
    router.push({
        path: item?.path,
        query: item?.query
    });
    showMenuModel(item?.path, item?.query);
}

链接

Logo

前往低代码交流专区

更多推荐