1. Vue 3 + TypeScript 全栈开发实战指南
全栈开发已经成为现代Web开发的主流模式,而Vue 3和TypeScript的组合为我们提供了一套强大而优雅的解决方案。作为一名长期奋战在一线的全栈开发者,我想分享一些在实际项目中积累的实战经验。
Vue 3的Composition API与TypeScript的类型系统简直是天作之合。它们不仅能让我们的代码更加健壮,还能显著提升开发效率。特别是在大型项目中,这种组合的优势会更加明显。
1.1 为什么选择Vue 3 + TypeScript?
类型安全是TypeScript最大的卖点。在Vue 3中,我们可以为组件props、emits、data等定义精确的类型,这能帮助我们在开发阶段就发现潜在的问题,而不是等到运行时才暴露出来。
Vue 3的响应式系统重构也让它对TypeScript的支持更加友好。新的ref和reactiveAPI与TypeScript的类型推断配合得天衣无缝。比如:
typescript复制const count = ref(0); // 自动推断为Ref<number>
const user = reactive({
name: '张三',
age: 25
}); // 自动推断为{ name: string; age: number }
在实际项目中,这种类型推断能为我们节省大量手动声明类型的时间。
1.2 全栈架构设计
一个典型的Vue 3 + TypeScript全栈应用通常采用以下架构:
code复制├── client/ # 前端项目
│ ├── src/
│ │ ├── api/ # API请求封装
│ │ ├── components/# 组件
│ │ ├── router/ # 路由
│ │ ├── stores/ # 状态管理(Pinia)
│ │ └── views/ # 页面视图
│ └── vite.config.ts # Vite配置
│
├── server/ # 后端项目
│ ├── src/
│ │ ├── controllers# 控制器
│ │ ├── models/ # 数据模型
│ │ ├── routes/ # 路由
│ │ └── services/ # 业务逻辑
│ └── package.json
│
└── shared/ # 共享代码
└── types/ # 共享类型定义
这种架构的关键在于前后端分离的同时,通过共享类型定义保持一致性。我们会在后面的章节详细讨论如何实现这一点。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 前端实现详解
2.1 项目初始化与配置
首先,我们使用Vite来初始化项目:
bash复制npm create vite@latest my-app --template vue-ts
这会给我们的项目配置好Vue 3和TypeScript的基本环境。接下来,我们需要做一些额外的配置来优化开发体验。
tsconfig.json关键配置:
json复制{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"strict": true,
"jsx": "preserve",
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": ".",
"paths": {
"@/*": ["src/*"]
},
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules"]
}
提示:配置
baseUrl和paths可以让我们使用@/别名来引用src目录下的文件,这在大型项目中特别有用。
2.2 API请求封装
在实际项目中,我们通常会封装一个统一的HTTP客户端。下面是一个基于axios的完整实现:
typescript复制// src/api/http.ts
import axios, { AxiosRequestConfig, AxiosResponse } from 'axios';
import { useUserStore } from '@/stores/user';
// 创建axios实例
const http = axios.create({
baseURL: import.meta.env.VITE_API_BASE_URL,
timeout: 10000,
headers: {
'Content-Type': 'application/json'
}
});
// 请求拦截器
http.interceptors.request.use((config: AxiosRequestConfig) => {
const userStore = useUserStore();
if (userStore.token) {
config.headers = config.headers || {};
config.headers.Authorization = `Bearer ${userStore.token}`;
}
return config;
}, (error) => {
return Promise.reject(error);
});
// 响应拦截器
http.interceptors.response.use((response: AxiosResponse) => {
return response.data;
}, (error) => {
if (error.response?.status === 401) {
// 处理未授权错误
const userStore = useUserStore();
userStore.logout();
window.location.href = '/login';
}
return Promise.reject(error);
});
export default http;
这个封装实现了以下功能:
- 统一的baseURL配置
- 自动添加认证token
- 统一的错误处理
- 简化的响应数据提取
2.3 组件开发实践
让我们看一个典型的用户列表组
