Vue 3 + TypeScript 企业级项目实战:从架构设计到性能优化

Vue 3 配合 TypeScript 是现代前端开发的主流组合。作为冉冉博客的前端教程系列,今天分享一个企业级项目的完整架构设计。

一、项目结构设计

清晰的项目结构是大型项目的基础:

src/
├── assets/              # 静态资源
├── components/          # 公共组件
│   ├── base/           # 基础组件 (Button, Input...)
│   ├── business/        # 业务组件
│   └── layout/         # 布局组件
├── composables/        # 组合式函数
│   ├── useAuth.ts
│   ├── useFetch.ts
│   └── usePagination.ts
├── directives/          # 自定义指令
├── hooks/              # 生命周期钩子
├── plugins/            # 插件配置
├── router/             # 路由配置
├── services/           # API 服务层
├── stores/             # 状态管理 (Pinia)
├── types/              # TypeScript 类型定义
├── utils/              # 工具函数
├── views/              # 页面组件
└── App.vue

二、TypeScript 类型定义

完善的类型定义是代码质量的保障:

// types/api.ts
interface ApiResponse {
  code: number;
  data: T;
  message: string;
}

interface PageParams {
  page: number;
  pageSize: number;
}

interface PageResult {
  list: T[];
  total: number;
  page: number;
  pageSize: number;
}

// types/user.ts
interface User {
  id: number;
  username: string;
  email: string;
  avatar?: string;
  roles: string[];
  createdAt: string;
}

type UserStatus = 'active' | 'inactive' | 'banned';

三、Pinia 状态管理

// stores/user.ts
import { defineStore } from 'pinia';
import { ref, computed } from 'vue';
import type { User } from '@/types';

export const useUserStore = defineStore('user', () => {
  const userInfo = ref(null);
  const token = ref('');
  
  const isLoggedIn = computed(() => !!token.value);
  const isAdmin = computed(() => userInfo.value?.roles.includes('admin'));
  
  async function login(username: string, password: string) {
    const res = await api.login({ username, password });
    token.value = res.data.token;
    userInfo.value = res.data.user;
  }
  
  function logout() {
    token.value = '';
    userInfo.value = null;
  }
  
  return { userInfo, token, isLoggedIn, isAdmin, login, logout };
});

四、组合式函数封装

提取复用逻辑,提高代码质量:

// composables/usePagination.ts
import { ref, computed } from 'vue';
import type { PageParams, PageResult } from '@/types';

export function usePagination(
  fetchFn: (params: PageParams) => Promise>
) {
  const list = ref([]);
  const loading = ref(false);
  const total = ref(0);
  const page = ref(1);
  const pageSize = ref(20);
  
  const totalPages = computed(() => Math.ceil(total.value / pageSize.value));
  
  async function loadData() {
    loading.value = true;
    try {
      const res = await fetchFn({ page: page.value, pageSize: pageSize.value });
      list.value = res.data.list;
      total.value = res.data.total;
    } finally {
      loading.value = false;
    }
  }
  
  function setPage(newPage: number) {
    page.value = newPage;
    loadData();
  }
  
  return { list, loading, total, page, pageSize, totalPages, loadData, setPage };
}

五、API 服务层设计

// services/user.ts
import type { User, ApiResponse } from '@/types';

export const userService = {
  getList(params: { page: number; pageSize: number }) {
    return http.get>('/users', { params });
  },
  
  getById(id: number) {
    return http.get>(`/users/${id}`);
  },
  
  create(data: Partial) {
    return http.post>('/users', data);
  },
  
  update(id: number, data: Partial) {
    return http.put>(`/users/${id}`, data);
  },
  
  delete(id: number) {
    return http.delete>(`/users/${id}`);
  },
};

六、路由权限控制

// router/guard.ts
import type { Router } from 'vue-router';
import { useUserStore } from '@/stores/user';

export function setupRouterGuard(router: Router) {
  router.beforeEach(async (to, from, next) => {
    const userStore = useUserStore();
    const requiresAuth = to.meta.requiresAuth;
    const requiredRoles = to.meta.roles as string[] | undefined;
    
    if (requiresAuth && !userStore.isLoggedIn) {
      next('/login');
      return;
    }
    
    if (requiredRoles && !userStore.hasRole(requiredRoles)) {
      next('/403');
      return;
    }
    
    next();
  });
}

七、性能优化技巧

  • 路由懒加载:按模块拆分,配合预加载策略
  • 组件懒加载:大组件使用 defineAsyncComponent
  • 图片优化:WebP 格式、懒加载、CDN
  • Tree Shaking:按需引入,清理无用代码
  • 虚拟列表:大数据列表使用虚拟滚动
  • 缓存策略:HTTP 缓存、Vue 缓存

Vue 3 + TypeScript 是现代前端开发的黄金组合。掌握这些架构设计和最佳实践,能让你在企业级项目中游刃有余。更多前端干货,欢迎持续关注冉冉博客。

© 版权声明
THE END
喜欢就支持一下吧
点赞10 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容