1. 为什么选择Vue 3 + TypeScript全栈开发
三年前接手一个电商后台项目时,我还在用Vue 2 + JavaScript的经典组合。随着项目规模扩大,类型错误导致的线上事故频发,维护成本呈指数级增长。直到将代码迁移到Vue 3 + TypeScript环境后,开发效率提升了40%,线上错误减少了75%。这种技术组合正在成为现代前端开发的事实标准。
Vue 3的Composition API彻底改变了我们组织代码的方式。在管理用户权限模块时,以前分散在data、methods、computed中的逻辑,现在可以聚合在useUserPermissions组合函数中。配合TypeScript的接口定义,新成员能在一天内理解权限校验流程,这在以前需要至少一周的熟悉时间。
2. 环境搭建与工程化配置
2.1 项目初始化最佳实践
使用Vite创建项目时,我推荐以下命令:
bash复制npm create vite@latest my-vue-app --template vue-ts
这比传统vue-cli创建的模板有显著优势:
- 冷启动速度快10倍以上
- 内置对.ts和.vue文件的处理
- 默认包含TypeScript基础配置
在最近的企业级项目中,我的tsconfig.json配置包含这些关键项:
json复制{
"compilerOptions": {
"strict": true,
"noImplicitAny": false,
"moduleResolution": "node",
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"baseUrl": "./",
"paths": {
"@/*": ["src/*"]
}
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.vue"]
}
重要提示:设置"strict": true虽然会增加初期类型定义工作量,但能避免90%的类型相关运行时错误
2.2 前端工程化深度配置
在构建企业级应用时,这些配置必不可少:
- ESLint配置:
javascript复制module.exports = {
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:vue/vue3-recommended'
],
rules: {
'vue/multi-word-component-names': 'off',
'@typescript-eslint/no-explicit-any': 'warn'
}
}
- 样式方案选择:
- 中小项目:Tailwind CSS + PostCSS
- 复杂项目:SCSS模块化 + BEM命名规范
- UI库项目:CSS-in-JS (如styled-components)
- axios封装示例:
typescript复制// src/utils/http.ts
import axios from 'axios'
const service = axios.create({
baseURL: import.meta.env.VITE_API_URL,
timeout: 15000
})
service.interceptors.request.use(config => {
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
})
export default service
3. Vue 3核心开发模式
3.1 Composition API实战技巧
在开发数据看板时,我总结出这些最佳实践:
- 逻辑关注点分离:
typescript复制// useDashboardData.ts
export default function useDashboardData() {
const loading = ref(false)
const chartData = reactive({
visits: [],
sales: []
})
const fetchData = async (params: DashboardParams) => {
loading.value = true
try {
const res = await api.getDashboardData(params)
chartData.visits = res.visits
chartData.sales = res.sales
} finally {
loading.value = false
}
}
return {
loading,
chartData,
fetchData
}
}
- 类型安全增强:
typescript复制interface User {
id: number
name: string
roles: string[]
}
const user = ref<User>({
id: 0,
name: '',
roles: []
})
3.2 组件开发进阶模式
- Props类型定义:
typescript复制const props = defineProps({
// 基本类型检查
title: {
type: String,
required: true
},
// 带默认值的数字
size: {
type: Number,
default: 100
},
// 自定义验证函数
validator: {
type: Function,
default: () => true
}
})
- 自定义事件类型:
typescript复制const emit = defineEmits<{
(e: 'update:modelValue', value: string): void
(e: 'submit', payload: FormData): void
}>()
4. 全栈架构设计与实现
4.1 后端服务集成方案
在最近的项目中,我采用NestJS作为后端框架,其优势在于:
- 完美支持TypeScript
- 模块化架构清晰
- 丰富的装饰器语法
用户模块的典型实现:
typescript复制// user.controller.ts
@Controller('users')
export class UsersController {
constructor(private readonly usersService: UsersService) {}
@Get()
async findAll(): Promise<User[]> {
return this.usersService.findAll()
}
@Post()
async create(@Body() createUserDto: CreateUserDto): Promise<User> {
return this.usersService.create(createUserDto)
}
}
4.2 数据库交互层优化
使用TypeORM时,这些技巧很实用:
- 实体定义示例:
typescript复制@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number
@Column({ length: 50 })
username: string
@Column({ select: false })
password: string
@CreateDateColumn()
createdAt: Date
}
- 事务处理模式:
typescript复制async transferMoney(fromId: number, toId: number, amount: number) {
await this.connection.transaction(async manager => {
await manager.decrement(User, { id: fromId }, 'balance', amount)
await manager.increment(User, { id: toId }, 'balance', amount)
})
}
5. 性能优化实战记录
5.1 前端性能提升技巧
- 组件懒加载:
typescript复制const UserProfile = defineAsyncComponent(() =>
import('./components/UserProfile.vue')
)
- API请求优化:
typescript复制// 使用Promise.all并行请求
const [userData, orders] = await Promise.all([
api.getUser(userId),
api.getOrders(userId)
])
- 虚拟滚动实现:
vue复制<template>
<RecycleScroller
:items="largeList"
:item-size="50"
key-field="id"
v-slot="{ item }"
>
<div class="item">{{ item.name }}</div>
</RecycleScroller>
</template>
5.2 后端性能关键指标
在压力测试中发现的优化点:
- 数据库查询优化前:
sql复制SELECT * FROM orders WHERE user_id = 1
优化后:
sql复制SELECT id, order_no, amount FROM orders
WHERE user_id = 1
ORDER BY created_at DESC
LIMIT 20
- 缓存策略实现:
typescript复制@Injectable()
export class ProductsService {
constructor(
@Inject(CACHE_MANAGER) private cacheManager: Cache,
private productsRepository: Repository<Product>
) {}
async findOne(id: number): Promise<Product> {
const cached = await this.cacheManager.get<Product>(`product_${id}`)
if (cached) return cached
const product = await this.productsRepository.findOne(id)
await this.cacheManager.set(`product_${id}`, product, { ttl: 3600 })
return product
}
}
6. 部署与监控方案
6.1 现代化部署流程
我的CI/CD配置示例(GitHub Actions):
yaml复制name: Deploy Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
- name: Deploy to Server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_HOST }}
username: ${{ secrets.SSH_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /var/www/my-app
git pull origin main
npm ci
pm2 restart my-app
6.2 监控告警配置
前端监控推荐方案:
typescript复制// main.ts
import * as Sentry from '@sentry/vue'
const app = createApp(App)
Sentry.init({
app,
dsn: 'your-dsn',
integrations: [
new Sentry.BrowserTracing({
routingInstrumentation: Sentry.vueRouterInstrumentation(router)
})
],
tracesSampleRate: 0.2
})
后端健康检查端点:
typescript复制@Get('health')
healthCheck() {
return {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime()
}
}
7. 典型问题解决实录
7.1 TypeScript类型扩展问题
处理第三方库类型缺失的解决方案:
typescript复制// src/types/vue.d.ts
import { ComponentCustomProperties } from 'vue'
declare module '@vue/runtime-core' {
interface ComponentCustomProperties {
$filters: {
formatDate: (date: Date) => string
}
}
}
7.2 跨域解决方案
生产环境推荐的CORS配置:
typescript复制// main.ts
app.enableCors({
origin: ['https://your-domain.com'],
methods: ['GET', 'POST', 'PUT', 'DELETE'],
allowedHeaders: ['Content-Type', 'Authorization']
})
开发环境代理配置(vite.config.ts):
typescript复制server: {
proxy: {
'/api': {
target: 'http://localhost:3000',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
8. 项目架构演进思考
在经历多个Vue 3全栈项目后,我总结出这些架构原则:
- 前端分层架构:
- 视图层:只处理UI渲染和用户交互
- 逻辑层:处理业务规则和状态管理
- 服务层:封装API请求和数据转换
- 后端模块划分:
code复制src/
├── modules/
│ ├── auth/
│ ├── users/
│ └── products/
├── shared/
│ ├── utils/
│ └── interceptors/
└── main.ts
- 共享类型定义:
typescript复制// shared/types/index.ts
export interface Pagination<T> {
data: T[]
total: number
page: number
limit: number
}
// 前端使用
const { data } = await api.get<Pagination<User>>('/users')
// 后端使用
@Get()
async findAll(): Promise<Pagination<User>> {
// ...
}
在最近的项目中,我们将前端类型定义抽离为独立npm包,通过内部仓库共享给前后端,彻底解决了类型同步问题。这种方案虽然初期配置复杂,但长期维护成本降低了60%以上。