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',
});
};