Vue3 Admin Template Without UI‑Framework Dependency – Features, Layout, Routing, State Management, and SVG Icon Builder

This article presents a lightweight, UI‑framework‑free Vue3 admin template, detailing its visual style configuration, core layout, permission‑based routing, TypeScript‑based state handling, custom AJAX request wrapper, and an SVG icon bundler, along with code examples and package information.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Vue3 Admin Template Without UI‑Framework Dependency – Features, Layout, Routing, State Management, and SVG Icon Builder

Overview

This document introduces a lightweight, UI‑framework‑free admin template built with vue.js (Vue 3) that provides visual style configuration, a dynamic layout system, permission‑based routing, TypeScript‑friendly state management, custom AJAX request handling, and an SVG icon builder.

Key Features

Visual configuration of CSS through a dedicated css variable, allowing style changes without editing code.

Switchable layout styles (top bar + multi‑level side menu) with responsive design and custom scrollbar support.

Only essential dependencies: vue, vue-router, and a minimal set of utilities.

High compatibility and extensibility – any third‑party UI library can be added without modifying core components.

Package.json is deliberately minimal, containing only necessary dependencies and devDependencies.

Package Configuration

{
  "dependencies": {
    "nprogress": "0.2.0",
    "vue": "3.2.45",
    "vue-router": "4.1.6"
  },
  "devDependencies": {
    "@types/node": "~18.15.11",
    "@types/nprogress": "0.2.0",
    "@vitejs/plugin-vue": "4.1.0",
    "@vitejs/plugin-vue-jsx": "3.0.1",
    "sass": "~1.61.0",
    "typescript": "5.0.4",
    "vite": "4.2.1",
    "vue-tsc": "1.2.0"
  }
}

Core Layout

The layout combines a top bar and a collapsible side menu that can be completely hidden by moving it off‑screen, maximizing the content area. Visual style can be edited through the built‑in CSS configurator, eliminating the need to read CSS files.

Routing and Permission Control

Routing inherits the standard vue-router structure. Permissions are defined in the meta.auth array, while meta.name serves as a unique key for route caching.

import { RouteRecordRaw } from "vue-router";

export interface RouteMeta {
  /** Sidebar menu name, document.title */
  title: string;
  /** External link, takes precedence over path */
  link?: string;
  /** SVG icon name */
  icon?: string;
  /** Hide this route from the sidebar */
  hidden?: boolean;
  /** Enable keep‑alive caching */
  keepAlive?: boolean;
  /** Array of user type IDs that can access the route */
  auth?: Array<number>;
}

/** Custom route type extending RouteRecordRaw */
export type RouteItem = {
  name?: string;
  children?: Array<RouteItem>;
  meta: RouteMeta;
} & RouteRecordRaw;

State Management

With Vue 3, the project avoids Vuex and instead uses TypeScript Readonly declarations for state objects, providing a simpler and more type‑safe approach.

Network Requests

A lightweight native ajax wrapper is used. The request function returns a promise that resolves to an object where res.code === 1 indicates success.

export interface TableItem {
  id: number;
  type: "load" | "update";
  time: string;
}

/**
 * @param params
 */
export function getData(params: PageInfo) {
  return request<ApiResultList<TableItem>>("GET", "/getList", params);
}

Example component usage:

<script lang="ts" setup>
import { ref } from "vue";
import { type TableItem, getData } from "api.ts";

const tableData = ref<TableItem>([]);

async function getTableData() {
  const res = await getData({ pageSize: 10, currentPage: 1 });
  if (res.code === 1) {
    tableData.value = res.data.list; // .list is of type TableItem
    // do some ...
  }
}
</script>

SVG Icon Builder

SVG files from a designated directory are transformed into <symbol> elements and injected into the page body, enabling easy use of icons via <svg><use>.

import { readFileSync, readdirSync } from "fs";

let idPerfix = "";
const svgTitle = /<svg([^>+].*?)>/;
const clearHeightWidth = /(width|height)="([^>+].*?)"/g;
const hasViewBox = /(viewBox="[^"]+"))/g;
const clearReturn = /(\r)|(
)/g;

function findSvgFile(dir: string): Array<string> {
  const svgRes: Array<string> = [];
  const dirents = readdirSync(dir, { withFileTypes: true });
  dirents.forEach(function (dirent) {
    if (dirent.isDirectory()) {
      svgRes.push(...findSvgFile(dir + dirent.name + "/"));
    } else {
      const svg = readFileSync(dir + dirent.name)
        .toString()
        .replace(clearReturn, "")
        .replace(svgTitle, function (_, group) {
          let width = 0;
          let height = 0;
          let content = group.replace(clearHeightWidth, function (val1, val2, val3) {
            if (val2 === "width") width = val3;
            else if (val2 === "height") height = val3;
            return "";
          });
          if (!hasViewBox.test(group)) {
            content += `viewBox="0 0 ${width} ${height}"`;
          }
          return `<symbol id="${idPerfix}-${dirent.name.replace(".svg", "")}" ${content}>`;
        })
        .replace("</svg>", "</symbol>");
      svgRes.push(svg);
    }
  });
  return svgRes;
}

export function svgBuilder(path: string, perfix = "icon") {
  if (path.trim() === "") return;
  idPerfix = perfix;
  const res = findSvgFile(path);
  return {
    name: "svg-transform",
    transformIndexHtml(html: string) {
      return html.replace("<body>", `<body>
        <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" style="position: absolute; width: 0; height: 0">
          ${res.join("")}
        </svg>`);
    }
  };
}

Conclusion

The template offers a minimal‑dependency, highly customizable admin UI for Vue 3 projects, covering visual styling, routing, state, data fetching, and SVG icon management, making it suitable for developers who prefer to build their own UI components rather than rely on third‑party UI libraries.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

TypeScriptState ManagementroutingSVGAdmin Template
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.