Building a Vue Admin Dashboard with TypeScript and Element UI

The foundation of this application relies on a centralized layout structure located within the src/layout directory. This pattern organizes the shell of the application separately from the core business logic, allowing for a modular design.

The recommended directory structure for the layout module is as follows:

src/
└── layout/
    ├── components/
    │   ├── index.ts          # Barrel file for component exports
    │   ├── Navbar.vue        # Sidebar navigation
    │   ├── AppMain.vue       # Primary route display area
    │   └── Prompt.vue        # Leftmost structural component
    ├── Layout.vue            # Root layout wrapper
    └── styles.scss           # Global style definitions

Within the component barrel file (index.ts), it is efficeint to utilize ES6 shorthand property names when exporting components. This improves code readability and reduces verbosity.

import Navbar from './Navbar.vue';
import AppMain from './AppMain.vue';
import Prompt from './Prompt.vue';

export default {
  name: 'LayoutComponents',
  components: {
    Navbar,
    AppMain,
    Prompt
  }
};

Integrating Element UI

To implement the UI library, the first step is to add the dependency to the project.

npm install element-ui

Subsequently, the library styles must be imported. This can be done in the main entry file or via a link tag in public/index.html. The programatic approach in src/main.ts is generally preferred for maintainability.

import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';

Vue.use(ElementUI);

When using TypeScript, it is crucial to ensure that properties referenced in the HTML template are marked with the public access modifier. Properties marked as private will not be accessible in the template, although this may not always trigger a compilation error.

HTTP Client Configuration with Axios

For network requests, we encapsulate Axios to handle global configurations, such as base URLs, timeouts, and authorization tokens. The following wrapper creates a centralized HTTP service.

import axios, { AxiosPromise } from 'axios';
import { Message } from 'element-ui';
import { getAuthToken } from '@/utils/auth'; // Helper to retrieve session token

interface RequestOptions {
  url: string;
  method: 'get' | 'post' | 'put' | 'delete';
  data?: any;
  params?: any;
}

const apiClient = axios.create({
  baseURL: 'https://api.example.com/v1',
  timeout: 100000,
});

apiClient.interceptors.request.use(config => {
  const token = getAuthToken();
  if (token) {
    config.headers['Authorization'] = `Bearer ${token}`;
  }
  return config;
}, error => {
  return Promise.reject(error);
});

export default function requestService(options: RequestOptions): AxiosPromise {
  const httpConfig: any = {
    method: options.method,
    url: options.url,
  };

  if (options.method === 'get') {
    httpConfig.params = options.data || options.params;
  } else {
    httpConfig.data = options.data || options.params;
    httpConfig.headers = {
      'Content-Type': 'application/json;charset=UTF-8',
    };
  }

  return new Promise((resolve, reject) => {
    apiClient(httpConfig).then(response => {
      // Handle specific response codes if necessary
      if (response.data && response.data.code === -3) {
        Message.error('Session expired');
      }
      resolve(response.data);
    }).catch(error => {
      Message.error(error.message || 'Request failed');
      reject(error);
    });
  });
}

Below is an example of how to define a specific API module using the configured service.

import requestService from '@/utils/request';

/**
 * Retrieves user menu permissions based on User ID
 * @param userId - The unique identifier of the user
 */
export const fetchUserMenu = (userId: string | number) => {
  return requestService({
    url: `/system/menu/${userId}`,
    method: 'get',
  });
};

Tags: vue TypeScript element-ui axios http-client

Posted on Thu, 18 Jun 2026 18:07:19 +0000 by neofox