DukeDuke
主页
项目文档
技术文档
  • 单机版
  • 微服务
  • 代办项目
  • 优鲜项目
项目管理
关于我们
主页
项目文档
技术文档
  • 单机版
  • 微服务
  • 代办项目
  • 优鲜项目
项目管理
关于我们
  • 技术文档

    • 网络原理

      • 交换机
      • 路由器
      • TCP/IP协议
      • HTTP 与 HTTPS
    • 软件架构

      • 什么是软件架构
      • 分层架构
      • 微服务架构
      • 事件驱动架构
      • 领域驱动设计(DDD)
      • 架构图
      • 高并发系统
    • Vue3

      • Vue3简介
      • Vue3响应式系统
      • Vue3组合式API
      • Vue3生命周期
      • Vue3模板语法
      • Vue3组件系统
      • Vue3 路由系统
      • Vue3 状态管理
      • Vue3 性能优化
      • Vue3 TypeScript 支持
      • Vue3 项目实战
      • VUE 面试题大全
      • Node.js 安装
    • JAVA

      • JVM

        • 认识JVM
        • JVM类加载器
        • 运行时数据区
        • 执行引擎
        • 本地方法接口
        • 本地方法库
        • JVM垃圾回收
        • JVM性能监控
        • JVM调优
      • 设计模式
        • 单例模式
        • 工厂模式
        • 策略模式
        • 适配器模式
        • 建造者模式
        • 原型模式
        • 装饰器模式
        • 代理模式
        • 外观模式
        • 享元模式
        • 组合模式
        • 桥接模式
      • Java多线程

        • Java 线程基础详解
        • Java 线程池详解
        • Java ThreadLocal 详解
        • Java volatile 详解
        • Java 线程间通信详解
        • Java 线程安全详解
        • Java 线程调度详解
        • Java 线程优先级详解

        • Java 线程中断详解
        • Java 线程死锁详解
      • Java反射
      • Java 面试题

        • Java 基础概念面试题
        • Java 面向对象编程面试题
        • Java 集合框架面试题
        • Java 多线程与并发面试题
        • JVM 与内存管理面试题
        • Java I/O 与 NIO 面试题
        • Java 异常处理面试题
        • Java 反射与注解面试题
        • Java Spring 框架面试题
        • Java 数据库与 JDBC 面试题
        • Java 性能优化面试题
        • Java 实际项目经验面试题
        • Java 高级特性面试题
        • Java 面试准备建议
    • Python

      • Python简介
      • Python安装
      • Python hello world
      • Python基础语法
      • Python数据类型
      • Python数字
      • Python字符串
      • Python列表
      • Python元组
      • Python字典
      • Python日期时间
      • Python文件操作
      • Python异常处理
      • Python函数
      • Python类
      • Python模块
      • Python包
      • Python多线程
      • Python面向对象
      • Python爬虫
      • Django web框架
      • Python 面试题

        • Python 面试题导航
        • Python 基础概念
        • Python 面向对象编程
        • Python 数据结构
        • Python 高级特性
        • Python 框架
        • Python 性能优化
        • Python 项目经验
    • Spring

      • Spring
      • Springboot
      • Spring Security 安全框架
      • SpringBoot 中的事件详解
      • SpringBoot 中的定时任务详解
      • SpringBoot 自动装配原理与源码解释
    • Mybatis

      • Mybatis
      • Mybatis-Plus
    • 数据库

      • Redis

        • Redis简介
        • Redis(单机)安装
        • Redis配置
        • Redis数据结构
        • RDB、AOF 和混合持久化机制
        • Redis内存管理
        • Redis缓存一致性
        • Redis缓存穿透
        • Redis缓存击穿
        • Redis缓存雪崩
        • Redis Lua脚本
        • Redis主从复制
        • Redis哨兵模式
        • Redis集群
        • Redis数据分片
        • Redis CPU使用率过高
        • Redis面试题
      • MySQL

        • MySQL简介
        • MySQL安装
        • MySQL配置
        • MYSQL日常维护
        • MYSQL优化-慢查询
        • MYSQL优化-索引
        • MYSQL数据库设计规范
    • 消息队列

      • RocketMQ
      • Kafka
      • RabbitMQ
      • 消息队列面试题
    • 微服务

      • SpringCloud 微服务
      • Eureka 注册中心
      • Nacos 注册中心
      • Gateway 网关
      • Feign 服务调用
      • Sentinel 限流 与 熔断
      • Seata 分布式事务
      • CAP 理论
      • Redis 分布式锁
      • 高并发系统设计
    • ELK日志分析系统

      • Elasticsearch 搜索引擎
      • Logstash 数据处理
      • Kibana 可视化
      • ELK 实战
    • 开放API

      • 开放API设计
      • 开放API示例项目
    • 人工智能

      • 人工智能简介
      • 机器学习

      • 深度学习

      • 自然语言处理

      • 计算机视觉

        • CUDA与cuDNN详细安装
        • Conda 安装
        • Pytorch 深度学习框架
        • yolo 目标检测
        • TensorRT 深度学习推理优化引擎
        • TensorFlow 机器学习
        • CVAT 图像标注
        • Windows 下安装 CUDA、cuDNN、TensorRT、TensorRT-YOLO 环境
        • Windows10+CUDA+cuDNN+TensorRT+TensorRT-YOLO 部署高性能YOLO11推理
    • 大数据

      • 大数据简介
      • Hadoop 数据存储
      • Flume 数据采集
      • Sqoop 数据导入导出
      • Hive 数据仓库
      • Spark 数据处理
      • Flink 数据处理
      • Kafka 数据采集
      • HBase 数据存储
      • Elasticsearch 搜索引擎
    • 图像处理

      • 图像处理简介
      • 医学图像web呈现
      • 医学图像处理
      • 切片细胞分离问题
    • 服务器&运维

      • Linux 系统

        • Linux 系统管理
        • Linux 网络管理
        • Linux 文件管理
        • Linux 命令大全
      • Nginx Web 服务器

        • Nginx 安装 与 配置
        • Nginx 负载均衡
        • Nginx SSL证书配置
        • Nginx Keepalived 高可用
      • Docker 容器

        • Docker 简介
        • Docker 安装与配置
        • Docker 命令
        • Docker 部署 Nginx
        • Docker 部署 MySQL
        • Docker 部署 Redis
      • 服务器

        • 塔式服务器
        • 机架式服务器
        • 刀片服务器
      • Git 版本控制
      • Jenkins 持续集成
      • Jmeter 性能测试
      • Let's Encrypt 免费SSL证书
    • 简历

      • 项目经理简历
      • 开发工程师简历

Vue3 项目实战

概述

本文档将介绍 Vue3 项目开发中的实战经验,包括项目结构设计、开发规范、最佳实践、常见问题解决方案等。通过实际项目案例,帮助开发者更好地应用 Vue3 技术。

项目结构设计

1. 标准项目结构

src/
├── assets/           # 静态资源
│   ├── images/      # 图片资源
│   ├── styles/      # 样式文件
│   └── icons/       # 图标文件
├── components/       # 公共组件
│   ├── common/      # 通用组件
│   ├── business/    # 业务组件
│   └── layout/      # 布局组件
├── views/           # 页面组件
│   ├── home/        # 首页
│   ├── user/        # 用户相关
│   └── admin/       # 管理后台
├── router/          # 路由配置
│   ├── index.js     # 主路由
│   ├── modules/     # 路由模块
│   └── guards.js    # 路由守卫
├── stores/          # 状态管理
│   ├── modules/     # 状态模块
│   └── index.js     # 状态入口
├── api/             # API 接口
│   ├── modules/     # 接口模块
│   ├── request.js   # 请求封装
│   └── types.ts     # 类型定义
├── utils/           # 工具函数
│   ├── auth.js      # 认证相关
│   ├── storage.js   # 存储工具
│   └── validate.js  # 验证工具
├── hooks/           # 组合式函数
│   ├── useAuth.js   # 认证钩子
│   ├── useTable.js  # 表格钩子
│   └── useForm.js   # 表单钩子
├── directives/      # 自定义指令
├── plugins/         # 插件配置
└── App.vue          # 根组件

2. 组件命名规范

// 组件文件命名:PascalCase
// UserProfile.vue, DataTable.vue

// 组件注册命名:PascalCase
export default {
  name: 'UserProfile',
  // ...
}

// 组件使用:kebab-case
<user-profile />
<data-table />

开发规范与最佳实践

1. 组合式 API 使用规范

响应式数据定义

import { ref, reactive, computed, watch } from "vue";

export default {
  setup() {
    // 基础类型使用 ref
    const count = ref(0);
    const loading = ref(false);
    const message = ref("");

    // 对象类型使用 reactive
    const formData = reactive({
      name: "",
      email: "",
      phone: "",
    });

    // 计算属性
    const isValid = computed(() => {
      return formData.name && formData.email;
    });

    // 监听器
    watch(
      formData,
      (newVal, oldVal) => {
        console.log("表单数据变化:", newVal);
      },
      { deep: true }
    );

    return {
      count,
      loading,
      message,
      formData,
      isValid,
    };
  },
};

逻辑复用 - 组合式函数

// hooks/useTable.js
import { ref, computed } from "vue";

export function useTable(api, options = {}) {
  const loading = ref(false);
  const data = ref([]);
  const pagination = ref({
    current: 1,
    pageSize: 10,
    total: 0,
  });

  const fetchData = async () => {
    loading.value = true;
    try {
      const response = await api({
        page: pagination.value.current,
        pageSize: pagination.value.pageSize,
        ...options.params,
      });
      data.value = response.data;
      pagination.value.total = response.total;
    } catch (error) {
      console.error("获取数据失败:", error);
    } finally {
      loading.value = false;
    }
  };

  const handlePageChange = (page) => {
    pagination.value.current = page;
    fetchData();
  };

  return {
    loading,
    data,
    pagination,
    fetchData,
    handlePageChange,
  };
}

// 使用示例
export default {
  setup() {
    const { loading, data, pagination, fetchData, handlePageChange } = useTable(
      userApi.getList,
      { params: { status: "active" } }
    );

    onMounted(() => {
      fetchData();
    });

    return {
      loading,
      data,
      pagination,
      handlePageChange,
    };
  },
};

2. 组件通信最佳实践

Props 和 Emit

// 子组件
export default {
  props: {
    title: {
      type: String,
      required: true
    },
    items: {
      type: Array,
      default: () => []
    }
  },
  emits: ['update', 'delete'],
  setup(props, { emit }) {
    const handleUpdate = (item) => {
      emit('update', item)
    }

    const handleDelete = (id) => {
      emit('delete', id)
    }

    return {
      handleUpdate,
      handleDelete
    }
  }
}

// 父组件
<template>
  <data-table
    :title="tableTitle"
    :items="tableData"
    @update="handleUpdate"
    @delete="handleDelete"
  />
</template>

Provide/Inject 跨层级通信

// 祖先组件
import { provide, ref } from 'vue'

export default {
  setup() {
    const theme = ref('light')
    const user = ref(null)

    provide('theme', theme)
    provide('user', user)
    provide('updateTheme', (newTheme) => {
      theme.value = newTheme
    })

    return {
      theme,
      user
    }
  }
}

// 后代组件
import { inject } from 'vue'

export default {
  setup() {
    const theme = inject('theme')
    const user = inject('user')
    const updateTheme = inject('updateTheme')

    return {
      theme,
      user,
      updateTheme
    }
  }
}

3. 路由管理最佳实践

路由配置

// router/index.js
import { createRouter, createWebHistory } from "vue-router";
import { useAuthStore } from "@/stores/auth";

const routes = [
  {
    path: "/",
    name: "Home",
    component: () => import("@/views/Home.vue"),
    meta: { requiresAuth: false },
  },
  {
    path: "/dashboard",
    name: "Dashboard",
    component: () => import("@/views/Dashboard.vue"),
    meta: { requiresAuth: true, roles: ["admin", "user"] },
    children: [
      {
        path: "profile",
        name: "Profile",
        component: () => import("@/views/Profile.vue"),
      },
    ],
  },
];

const router = createRouter({
  history: createWebHistory(),
  routes,
});

// 路由守卫
router.beforeEach((to, from, next) => {
  const authStore = useAuthStore();

  if (to.meta.requiresAuth && !authStore.isAuthenticated) {
    next("/login");
  } else if (to.meta.roles && !to.meta.roles.includes(authStore.userRole)) {
    next("/403");
  } else {
    next();
  }
});

export default router;

动态路由

// 动态添加路由
export function addDynamicRoutes(menus) {
  const dynamicRoutes = menus.map((menu) => ({
    path: menu.path,
    name: menu.name,
    component: () => import(`@/views/${menu.component}.vue`),
    meta: menu.meta,
  }));

  dynamicRoutes.forEach((route) => {
    router.addRoute(route);
  });
}

4. 状态管理最佳实践

Pinia Store 设计

// stores/user.js
import { defineStore } from "pinia";
import { ref, computed } from "vue";
import { userApi } from "@/api";

export const useUserStore = defineStore("user", () => {
  // 状态
  const user = ref(null);
  const token = ref("");
  const permissions = ref([]);

  // 计算属性
  const isAuthenticated = computed(() => !!token.value);
  const userRole = computed(() => user.value?.role || "guest");
  const hasPermission = computed(() => (permission) => {
    return permissions.value.includes(permission);
  });

  // 方法
  const login = async (credentials) => {
    try {
      const response = await userApi.login(credentials);
      user.value = response.user;
      token.value = response.token;
      permissions.value = response.permissions;

      // 持久化存储
      localStorage.setItem("token", response.token);
      localStorage.setItem("user", JSON.stringify(response.user));

      return response;
    } catch (error) {
      throw error;
    }
  };

  const logout = () => {
    user.value = null;
    token.value = "";
    permissions.value = [];
    localStorage.removeItem("token");
    localStorage.removeItem("user");
  };

  const updateProfile = async (profileData) => {
    try {
      const response = await userApi.updateProfile(profileData);
      user.value = { ...user.value, ...response };
      return response;
    } catch (error) {
      throw error;
    }
  };

  return {
    user,
    token,
    permissions,
    isAuthenticated,
    userRole,
    hasPermission,
    login,
    logout,
    updateProfile,
  };
});

性能优化实践

1. 组件懒加载

// 路由懒加载
const routes = [
  {
    path: "/dashboard",
    component: () => import("@/views/Dashboard.vue"),
  },
];

// 组件懒加载
import { defineAsyncComponent } from "vue";

const AsyncComponent = defineAsyncComponent(() =>
  import("@/components/HeavyComponent.vue")
);

2. 虚拟滚动

// 使用虚拟滚动处理大量数据
import { VirtualList } from 'vue-virtual-scroll-list'

export default {
  components: {
    VirtualList
  },
  setup() {
    const items = ref(Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` })))

    return {
      items
    }
  }
}

// 模板
<virtual-list
  :data-key="'id'"
  :data-sources="items"
  :data-component="ItemComponent"
  :estimate-size="50"
/>

3. 图片懒加载

// 自定义指令
const lazyLoad = {
  mounted(el, binding) {
    const observer = new IntersectionObserver((entries) => {
      entries.forEach(entry => {
        if (entry.isIntersecting) {
          el.src = binding.value
          observer.unobserve(el)
        }
      })
    })
    observer.observe(el)
  }
}

// 使用
<img v-lazy="imageUrl" alt="lazy image" />

常见问题与解决方案

1. 响应式数据丢失

// 问题:解构响应式对象会丢失响应性
const user = reactive({ name: "John", age: 30 });
const { name, age } = user; // 丢失响应性

// 解决方案1:使用 toRefs
import { toRefs } from "vue";
const { name, age } = toRefs(user); // 保持响应性

// 解决方案2:使用 computed
const name = computed(() => user.name);
const age = computed(() => user.age);

2. 内存泄漏

// 问题:事件监听器未清理
export default {
  setup() {
    const handleResize = () => {
      console.log("window resized");
    };

    window.addEventListener("resize", handleResize);

    // 解决方案:在 onUnmounted 中清理
    onUnmounted(() => {
      window.removeEventListener("resize", handleResize);
    });
  },
};

3. 异步组件加载失败

// 问题:异步组件加载失败时的处理
const AsyncComponent = defineAsyncComponent({
  loader: () => import("@/components/HeavyComponent.vue"),
  loadingComponent: LoadingSpinner,
  errorComponent: ErrorComponent,
  delay: 200,
  timeout: 3000,
  onError(error, retry, fail, attempts) {
    if (attempts <= 3) {
      retry();
    } else {
      fail();
    }
  },
});

测试策略

1. 单元测试

// 使用 Vitest 进行单元测试
import { describe, it, expect } from "vitest";
import { mount } from "@vue/test-utils";
import { createPinia } from "pinia";
import UserProfile from "@/components/UserProfile.vue";

describe("UserProfile", () => {
  it("renders user information correctly", () => {
    const wrapper = mount(UserProfile, {
      props: {
        user: {
          name: "John Doe",
          email: "john@example.com",
        },
      },
      global: {
        plugins: [createPinia()],
      },
    });

    expect(wrapper.text()).toContain("John Doe");
    expect(wrapper.text()).toContain("john@example.com");
  });
});

2. 集成测试

// 测试组件与 Store 的集成
import { createTestingPinia } from "@pinia/testing";

const wrapper = mount(Component, {
  global: {
    plugins: [
      createTestingPinia({
        initialState: {
          user: { user: { name: "Test User" } },
        },
      }),
    ],
  },
});

部署与构建

1. 环境配置

// .env.development
VITE_API_BASE_URL=http://localhost:3000
VITE_APP_TITLE=Vue3 App (Dev)

// .env.production
VITE_API_BASE_URL=https://api.example.com
VITE_APP_TITLE=Vue3 App

2. 构建优化

// vite.config.js
import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import { resolve } from "path";

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      "@": resolve(__dirname, "src"),
    },
  },
  build: {
    rollupOptions: {
      output: {
        manualChunks: {
          vendor: ["vue", "vue-router", "pinia"],
          utils: ["lodash-es", "dayjs"],
        },
      },
    },
    chunkSizeWarningLimit: 1000,
  },
});

项目监控与错误处理

1. 全局错误处理

// 全局错误处理器
app.config.errorHandler = (err, vm, info) => {
  console.error("全局错误:", err);
  console.error("错误信息:", info);

  // 发送错误到监控服务
  errorTracker.captureException(err, {
    extra: { info, component: vm?.$options?.name },
  });
};

// 未捕获的 Promise 错误
window.addEventListener("unhandledrejection", (event) => {
  console.error("未处理的 Promise 错误:", event.reason);
  event.preventDefault();
});

2. 性能监控

// 性能监控
import { onMounted } from "vue";

export default {
  setup() {
    onMounted(() => {
      // 监控页面加载性能
      if ("performance" in window) {
        const perfData = performance.getEntriesByType("navigation")[0];
        console.log(
          "页面加载时间:",
          perfData.loadEventEnd - perfData.loadEventStart
        );
      }
    });
  },
};

总结

Vue3 项目实战需要综合考虑项目结构、开发规范、性能优化、测试策略等多个方面。通过合理的架构设计和最佳实践,可以构建出高质量、可维护的 Vue3 应用。

关键要点:

  1. 合理规划项目结构,遵循约定优于配置的原则
  2. 充分利用组合式 API,提高代码复用性和可维护性
  3. 注重性能优化,从组件设计到构建配置都要考虑性能
  4. 完善的测试策略,确保代码质量和稳定性
  5. 监控和错误处理,及时发现和解决问题

通过不断实践和总结,你将能够掌握 Vue3 项目开发的核心技能,构建出优秀的前端应用。

最近更新:: 2025/8/29 08:36
Contributors: Duke
Prev
Vue3 TypeScript 支持
Next
VUE 面试题大全