模块一:专业基石 - 构筑自动化与企业级的开发环境
模块一:专业基石 - 构筑自动化与企业级的开发环境
Prorise模块一:专业基石 - 构筑自动化与企业级的开发环境
本模块任务清单
本模块将从零开始,构建一个功能完备、高度规范化的 Vue 3 企业级开发环境。我们将集成并深度配置所有核心依赖,建立一套全自动化的代码质量保障与提交体系。
通过以下 9 个核心任务,您将掌握构建企业级 Vue 3 开发环境的完整流程:
任务模块 | 任务名称 | 描述 |
---|---|---|
项目初始化 | 项目模板创建 | 使用 pnpm 和 Vite 创建纯净的 Vue + TypeScript 项目模板。 |
代码规范体系 | ESLint & Prettier 集成 | 集成 ESLint 和 Prettier ,采用 eslint.config.js 范式,统一代码质量与风格。 |
路径别名配置 | 开发效率基础设施 | 配置路径别名,为后续章节的模块引用提供基础支持。 |
UI 组件库集成 | Element Plus 按需导入 | 安装 Element Plus ,利用 unplugin-vue-components 实现组件按需自动导入。 |
国际化配置 | Element Plus 中文化 | 将 Element Plus 默认语言从英语切换为简体中文。 |
SCSS 企业级架构 | 样式系统构建 | 集成 SCSS ,建立企业级的样式架构和 Element Plus 主题定制方案。 |
核心服务集成 | 基础服务安装与配置 | 完成 TanStack Query , Pinia , Vue Router 和 Axios 的基础安装与初始化配置。 |
API 自动导入 | 开发效率优化 | 配置 API 自动导入,消除重复的 import 语句,提升编码效率。 |
自动化提交流程 | Husky & lint-staged | 配置 Husky 与 lint-staged ,在 Git 提交流程中强制执行代码检查。 |
1.1 项目初始化
我们从最基础的一步开始:创建一个全新的项目。
当前任务: 1.1 - 项目初始化
任务目标: 使用业界推荐的包管理器 pnpm
和构建工具 Vite
,快速生成一个标准的 Vue 3 + TypeScript 项目骨架。
1.1.1 设计思路与技术选型
在包管理器方面,我们优先选择 pnpm
,而非 npm
或 yarn
。pnpm
的核心优势体现在以下几个方面:
- 极致的磁盘空间效率:
pnpm
采用内容寻址和硬链接技术,确保相同版本的依赖在磁盘上只存储一份,极大地节省了存储空间。 - 闪电般的安装速度: 凭借对本地缓存的优先利用,
pnpm
在依赖安装速度上显著优于其竞争者。 - 严格的依赖管理:
pnpm
的非扁平化node_modules
结构从根本上解决了 “幽灵依赖” 问题,从而增强了项目的稳定性和可维护性。
在构建工具方面,Vite
是我们现代 Vue 项目开发的标准配置。其基于原生 ES 模块的开发服务器,提供了无与伦比的冷启动速度和热模块更新(HMR)性能,极大地提升了开发体验。
1.1.2 命令行操作
首先,请确保您的开发环境中已全局安装 pnpm
。如果尚未安装,可以通过 npm
执行以下命令进行安装:
1 | npm install -g pnpm |
接下来,打开终端并导航至您的工作目录。执行以下命令来启动项目创建流程:
1 | pnpm create vite |
Vite 的脚手架工具将引导您完成一系列项目配置选择。请按照以下配置项进行选择:
- Project name:
vue3-webShop
- Select a framework:
Vue
- Select a variant:
TypeScript
完成上述选择后,Vite 将在 /path/to/your/workspace/vue3-webShop
路径下完成项目骨架的搭建。随后,按照提示进入项目目录并安装所有依赖:
1 | cd vue3-webShop |
1.1.3 成果预览:初始项目结构
执行完以上命令后,您将获得一个纯净且标准的 Vite + Vue 3 项目结构,其目录概览如下:
1 | # vue3-webShop/ |
至此,项目的 “毛坯房” 已经搭建完毕。这是一个坚实且干净的起点,我们将在其之上,逐步添砖加瓦,构筑我们的应用大厦。
1.2 代码规范体系
在团队协作中,代码不仅是实现功能的工具,更是沟通的媒介。一套统一、自动化的代码规范体系,是保障项目长期可维护性、提升团队协作效率的基石。
当前任务: 1.2 - 代码规范体系
任务目标: 为项目集成 ESLint
(代码质量检查) 和 Prettier
(代码风格格式化),并采用最新的 eslint.config.js
范式,建立一套专业的、自动化的代码规范标准。
1.2.1 设计思路:质量与风格的分离
在配置之前,我们必须理解两个核心工具的职责边界:
- ESLint (代码质量卫士): 它的核心职责是 发现代码中的潜在错误和不合理的写法。例如,是否存在未被使用的变量、是否在
switch
语句中缺少break
等。它关心的是代码的 正确性 和 健壮性。 - Prettier (代码风格造型师): 它的职责非常纯粹,即 统一代码的格式。例如,是使用单引号还是双引号、行尾是否需要分号、代码行的最大宽度等。它只关心代码的 外观,不关心其逻辑。
我们的策略是让它们各司其职,并通过配置让它们完美协作:ESLint 负责修复代码质量问题,Prettier 负责最终的格式化,且 Prettier 的优先级更高,以避免两者在风格规则上的冲突。
1.2.2 核心依赖安装
现在,我们将为项目安装所有必需的 “纪律委员”。请在项目根目录下执行以下命令:
1 | pnpm add -D @eslint/js eslint eslint-config-prettier eslint-plugin-vue globals prettier typescript-eslint |
依赖解读:
eslint
&@eslint/js
: ESLint 本体及其官方核心规则集。typescript-eslint
: 用于让 ESLint 理解和校验 TypeScript 语法的核心插件。eslint-plugin-vue
: 专为.vue
单文件组件量身打造的规则插件。eslint-config-prettier
: 关键!用于关闭所有与 Prettier 冲突的 ESLint 规则,确保 Prettier 拥有最终的格式化决定权。prettier
: Prettier 本体。globals
: 用于预设浏览器、Node.js 等环境的全局变量,避免 ESLint 报错。
1.2.3 现代化 ESLint 配置
ESLint 的配置已全面转向基于 ES Module 的 eslint.config.js
文件。这种新范式提供了前所未有的灵活性。
现在,我们在项目根目录创建 eslint.config.js
文件,并填入以下内容。让我们来逐块解析它的结构:
1 | // eslint.config.js |
配置解读:
ignores
: 全局忽略配置。我们明确告诉 ESLint 不要检查构建产物、依赖、配置文件等,以提升检查效率并避免误报。languageOptions.globals
: 全局变量配置。我们引入了globals
包中预设的浏览器和 ES2021 环境的全局变量,这样在代码中使用window
、Promise
等就不会被 ESLint 判为未定义。eslintJs.configs.recommended
: 启用 ESLint 官方的核心推荐规则。...tseslint.configs.recommended
: 启用typescript-eslint
的推荐规则集,用于检查 TypeScript 代码。...eslintPluginVue.configs["flat/recommended"]
: 启用eslint-plugin-vue
针对 Vue 3 的推荐规则集。eslintConfigPrettier
: 关键步骤。此配置会禁用所有与 Prettier 格式化功能冲突的 ESLint 规则。它必须放在配置数组的靠后位置,以确保它能覆盖之前所有规则集中的样式规则。- 自定义规则: 这是我们项目的专属规则区。
files: ["**/*.vue"]
指定了这些规则仅对.vue
文件生效。parserOptions
: 为 Vue 文件的<script>
部分指定 TypeScript 解析器。rules
:'vue/multi-word-component-names': 'off'
: 关闭了组件名必须为多词的规则,在某些场景下(如根组件App.vue
)可以更灵活。'vue/html-self-closing'
: 配置了 HTML 元素的自闭合风格,增强代码一致性。'no-console'
,'no-debugger'
: 设置了在生产环境下(process.env.NODE_ENV === 'production'
)禁止使用console
和debugger
,这是非常重要的生产环境最佳实践。
1.3 路径别名配置
为了在后续开发中方便地引用 src
目录下的文件,避免使用复杂的相对路径,我们需要先设置路径别名。这是后续章节正常使用 @/
前缀的基础配置。
当前任务: 1.3 - 路径别名配置
任务目标: 配置 @
作为 src
目录的别名,为项目建立简洁的模块引用方式。
1.3.1 设计思路
在大型项目中,文件结构往往很深,使用相对路径会导致这样的引用:
1 | import { apiCall } from "../../../utils/http"; |
通过配置路径别名,我们可以将其简化为:
1 | import { apiCall } from "@/utils/http"; |
这不仅让代码更简洁,还避免了在移动文件时需要修改引用路径的问题。
1.3.2 Vite 配置
在项目根目录的 vite.config.ts
文件中添加路径别名配置:
1 | // vite.config.ts |
1.3.3 TypeScript 支持
为了让 TypeScript 理解这个路径别名,我们需要更新 TypeScript 配置。
方法一:如果您的项目使用单一 tsconfig.json
1 | { |
方法二:如果您的项目使用 tsconfig.app.json
(推荐)
1 | // tsconfig.app.json |
修改 TypeScript 配置文件后,请务必通过 VS Code 命令面板 (Ctrl+Shift+P
) 执行 TypeScript: Restart TS Server
命令来重启 TypeScript 服务,以确保路径提示生效。
1.3.4 功能测试
配置完成后,在任意 Vue 组件中尝试使用 @/
前缀:
1 | <script setup lang="ts"> |
如果 VS Code 能够正确提供路径提示和自动补全,说明配置成功。
1.4 UI 组件库与图标库集成
为项目引入一套成熟的 UI 组件库,是现代前端开发的标准实践。它能极大提升开发效率,保证 UI 的一致性和可访问性,让我们能专注于业务逻辑的实现。
当前任务: 1.4 - UI 组件库与图标库集成
任务目标: 为项目安装 Element Plus
及其官方图标库,并利用 unplugin-vue-components
、unplugin-auto-import
和 unplugin-icons
插件,实现组件 和图标 的按需自动导入。
1.4.1 设计思路:按需自动导入
在项目中引入 Element Plus 有两种方式:全局引入和按需导入。
- 全局引入: 简单直接,但会将所有组件和图标打包,导致最终构建产物体积过大。
- 按需导入: 只打包代码中实际使用到的组件,是生产环境的最佳实践。
为了实现优雅的按需导入,避免在每个文件中手动 import { ElButton } from 'element-plus'
和 import { Edit } from '@element-plus/icons-vue'
,我们借助 unplugin
系列插件来自动化这一过程。
1.4.2 核心依赖安装
我们将安装 element-plus
本体、其官方图标库,以及三个实现自动导入的 unplugin
插件。请在项目根目录下执行以下命令:
1 | # 1. 安装 element-plus 和图标库 |
依赖解读:
包名 | 核心职责 |
---|---|
element-plus | Element Plus 组件库本体。 |
@element-plus/icons-vue | Element Plus 的官方图标库,其中每个图标都是一个独立的 Vue 组件。 |
unplugin-auto-import | 自动导入 API,如 ElMessage 等 JS 调用方法。 |
unplugin-vue-components | 自动导入组件,扫描模板中的标签(如 <el-button> )并自动导入。 |
unplugin-icons | 一个强大的图标插件,可以与 unplugin-vue-components 协同工作,实现图标的自动导入。 |
@iconify-json/ep | Element Plus 图标的 Iconify 数据包,为 unplugin-icons 提供图标数据。 |
1.4.3 Vite 配置文件 (vite.config.ts
)
安装完依赖后,我们需要在 vite.config.ts
中启用并配置这些插件。
1 | // vite.config.ts |
配置解读:
IconsResolver
: 这是专门用于解析图标的解析器。enabledCollections: ['ep']
: 告诉解析器只启用 Element Plus 的图标集 (ep
是其简称)。
- 使用约定: 我们建立了一个清晰的图标使用约定:所有以
<i-ep-
开头的标签(例如<i-ep-edit />
),都会被自动识别为 Element Plus 的图标并导入。
1.4.4 TypeScript 类型支持 (Volar)
为了让 TypeScript 和 Volar 能够识别自动导入的组件和图标,我们需要确保 tsconfig.json
的 include
配置包含了插件自动生成的类型声明文件。
1 | // tsconfig.json |
修改配置后,你可能需要重启 VS Code 或执行 TypeScript: Restart TS Server
命令来让类型提示生效。
1.4.5 功能测试
配置完成后,我们来验证组件和图标是否都已成功集成。打开 src/App.vue
文件,替换为以下代码:
1 | <script setup lang="ts"></script> |
现在,启动开发服务器 (pnpm run dev
)。如果你能看到按钮和图标都正常显示,那么恭喜你,自动导入已成功配置!
1.4.6 深度解析:图标的两种用法 (手动 vs 自动)
你可能会有疑问:为什么我们不使用官方文档中常见的 import { Edit } from '@element-plus/icons-vue'
方式,而是用 <i-ep-edit />
?这是一个非常好的问题,理解它有助于你掌握现代前端的工程化思想。
等等,我平时用图标都是 import { Phone } from '@element-plus/icons-vue'
,然后在模板里用 :icon="Phone"
。你教的 <i-ep-phone />
是什么新语法?
问得好!你说的 手动导入 是 Vue 最经典、最直观的用法。而我们配置的 自动导入,是利用工具链提升效率的 工程化最佳实践。两者都能用,但后者能让你的代码更简洁。
有什么区别?
手动导入,你是在 运行时 告诉 Vue,“Phone
这个变量是一个组件”。而自动导入,是插件在 编译时 就帮你把 <i-ep-phone />
这个 “暗号” 直接替换成了真正的组件和导入语句。
我明白了!所以自动导入省去了我在 <script>
里写一大堆 import 的麻烦,想用哪个图标,直接在模板里写 “暗号” 就行了。
完全正确!这就是现代前端工程化的魅力所在——把重复的、机械的工作交给工具,让开发者专注于创造。
方法 A: 手动导入 (传统方式)
这是 Element Plus 官方文档中最常见的用法,依赖关系清晰。
- 代码示例:
1
2
3
4
5
6<script setup lang="ts">
import { Phone } from "@element-plus/icons-vue";
</script>
<template>
<el-link :icon="Phone">在线客服</el-link>
</template> - 优点: 依赖关系明确,无需额外配置。
- 缺点: 当使用大量图标时,
<script>
部分会变得非常冗长。
方法 B: 自动导入 (工程化实践)
这是我们通过插件配置实现的用法,开发体验极致高效。
- 代码示例:
1
2
3
4<template>
<!-- 无需在 script 中做任何事 -->
<el-button type="success"> <i-ep-edit /> 编辑按钮 </el-button>
</template> - 优点:
<script>
保持干净,开发效率极高,代码更整洁。 - 缺点: 需要前期配置,对于不熟悉配置的人来说有 “魔法” 成分。
特性 | 手动导入 (传统方式) | 自动导入 (工程化实践) |
---|---|---|
核心思想 | 运行时,开发者手动管理依赖 | 编译时,插件自动注入依赖 |
代码整洁度 | <script> 部分较长,依赖明确 | <script> 部分干净,模板即声明 |
开发效率 | 较低,需要手动导入 | 极高,开箱即用 |
推荐实践 | 偶尔需要将图标作为变量传递时使用 | 现代前端工程化的首选方案,适用于绝大部分场景 |
结论:
在本教程中,我们将 优先使用自动导入 的方式,因为它极大地提升了开发体验,是构建大型企业级项目的首选。理解这两种方式的差异,将让你对现代前端工具链有更深刻的认识。
1.5 国际化 (i18n) 配置
Element Plus 组件库默认的语言是英语。对于面向中文用户的项目,我们需要进行国际化配置,将提示文字、日期格式等转换为中文,以提供符合用户习惯的体验。
当前任务: 1.5 - 国际化 (i18n) 配置
任务目标: 将 Element Plus 组件的默认语言从英语(en)切换为简体中文(zh-cn)。
1.5.1 设计思路
Element Plus 提供了两种主流的国际化配置方案:
- 全局配置: 在应用入口文件 (
main.ts
) 中,通过app.use
传入全局配置对象。这是最常用、最直接的方式,一次配置,全局生效。 ElConfigProvider
组件: 使用ElConfigProvider
组件包裹根组件或部分组件树,可以实现全局或局部的语言配置。
对于我们整个应用都需要使用中文的场景,全局配置 是最佳选择。
1.5.2 全局配置实现
我们将修改 main.ts
文件,导入 Element Plus 的中文语言包并进行全局注册。
现在,让我们整合这段逻辑到 main.ts
文件中。如果架构师的 main.ts
中已经有 app.use(ElementPlus)
,请将其替换为带有配置对象的版本。
1 | // src/main.ts |
配置解读:
- 我们从
element-plus/dist/locale/
目录下导入了zh-cn.mjs
,这是一个包含了所有组件中文翻译的对象。 - 在调用
app.use(ElementPlus)
时,我们传入了第二个参数,一个配置对象{ locale: zhCn }
。Element Plus 内部会接收这个对象,并将zhCn
设为默认语言包。
1.5.3 功能测试
如何验证国际化配置是否生效?我们可以使用一个包含大量文本的组件,例如日期选择器 (ElDatePicker
)。
修改 src/App.vue
进行测试:
1 | <template> |
现在,运行项目。当你点击日期选择框时,弹出的面板中的 “一月”、“周一”、“今天” 等文字如果都显示为中文,则证明我们的国际化配置已成功生效。
现在,运行项目。当你点击日期选择框时,弹出的面板中的 “一月”、“周一”、“今天” 等文字如果都显示为中文,则证明我们的国际化配置已成功生效。
1.6 SCSS 企业级架构与主题定制
在企业级项目中,样式的可维护性、可扩展性和一致性至关重要。本节,我们将摒弃零散的样式文件,构建一套专业、分层的 SCSS 架构。我们将学习如何集成并定制 Element Plus,同时建立一套包含全局变量、基础规范、混入(Mixins)的完整体系,并通过一个统一的入口文件进行管理,最终由 Vite 实现高效的全局注入。
当前任务: 1.6 - 构建企业级 SCSS 架构
任务目标: 建立一套专业的、可扩展的 SCSS 文件结构。通过 Vite additionalData
全局注入编译时工具(变量、混入),并通过 main.ts
导入唯一的全局样式文件,实现最高效的样式管理方案。
1.6.1 设计思路:全局样式与编译工具的分离
一个顶级的样式架构必须清晰地分离两个概念:
- 全局样式表 (Global Stylesheet): 这是应用的基础外观,包含 CSS 重置、基础排版 (
body
,a
标签等) 和 Element Plus 的定制化样式。这些样式应该被编译成一个单一的 CSS 文件,并在应用入口 (main.ts
) 加载且仅加载一次。 - 编译时工具 (Compile-Time Tools): 这是我们在编写组件独有样式时需要的设计令牌和代码片段,如
$GLColor
变量和flex-center
混入。这些工具本身不产生 CSS,它们需要在 每个组件的<style>
块中都可用,以便我们遵循设计规范。
我们将通过 main.scss
文件来组织 全局样式表,并通过 Vite 的 additionalData
配置来全局提供 编译时工具。
1.6.2 依赖安装与文件结构创建
安装 SCSS 编译器与重置库:
1
pnpm add -D sass scss-reset
创建全新的样式文件结构:
在src/
目录下创建styles
文件夹,并建立以下专业结构:1
2
3
4
5
6
7
8
9
10
11src/
└── styles/
├── abstracts/
│ ├── _variables.scss # 全局变量
│ ├── _mixins.scss # 全局混入
│ └── _utilities.scss # 工具类
├── base/
│ └── _index.scss # 基础样式规范
├── element/
│ └── _index.scss # Element Plus 变量覆盖
└── main.scss # 唯一的全局样式总入口
1.6.3 编写抽象层 (Abstracts)
这是我们的 “工具箱”,包含所有不直接输出 CSS 的变量和混入。
1. _variables.scss
1 | // src/styles/abstracts/_variables.scss |
2. _mixins.scss
1 | // src/styles/abstracts/_mixins.scss |
3. _utilities.scss
1 | // src/styles/abstracts/_utilities.scss |
1.6.4 编写会输出 CSS 的样式层
这两个层级的文件会实际产出 CSS,它们需要显式地导入自己所依赖的变量。
1. base/_index.scss
1 | // src/styles/base/_index.scss |
2. element/_index.scss
1 | // src/styles/element/_index.scss |
1.6.5 编写全局样式入口 main.scss
此文件是 全局样式表的指挥中心,它按顺序编排所有会产出 CSS 的样式模块。
1 | // src/styles/main.scss |
1.6.6 理解工作流:最佳注入策略
架构师,我们现在有了 main.scss
总入口,还有 _variables.scss
这些工具文件。我们应该如何在 Vite 中配置,才能达到最佳的性能和开发体验?
这是一个关键问题。最粗暴的方法是在 additionalData
里注入 main.scss
,但这会导致 scss-reset
和 base
这些全局样式被重复打包进每一个组件的 CSS 中,造成代码冗余。
那该怎么办?
采用 分离策略。Vite 的 additionalData
只用来注入那些 不产出 CSS 的编译时工具——也就是我们的变量和混入。这样,每个组件的 <style>
块都能随时使用 $GLColor
或 @include flex-center
。
那 scss-reset
和 base
这些真正的全局样式呢?
它们由 main.scss
统一管理,而我们只需要在项目的 JavaScript 入口,也就是 main.ts
中,import '@/styles/main.scss'
一次。这样 Vite 就会把它们打包成一个独立的、被所有页面共享的 CSS 文件。一次加载,全局生效。这就是企业级的最佳实践。
1.6.7 实施最终配置
现在,我们将整合所有配置,实施我们讨论出的最佳注入策略。
1. 更新 vite.config.ts
1 | // vite.config.ts |
2. 更新 main.ts
1 | // src/main.ts |
1.6.8 清理与测试
确认
main.ts
: 确保import 'element-plus/dist/index.css'
已被彻底删除,因为我们的样式体系已经完美接管。功能测试: 重启 Vite 开发服务器。
- 全局样式: 页面基础排版(字体、背景色等)应已正确应用。这证明
main.scss
已被成功加载一次。 - Element Plus 定制:
<el-button type="primary">
按钮应显示为我们定义的$GLColor
。 - 组件内工具: 在任意 Vue 组件的
<style lang="scss">
块中,你都可以直接使用$GLColor
变量或@include flex-center;
混入来编写该组件的 独有样式,而无需任何手动导入。
- 全局样式: 页面基础排版(字体、背景色等)应已正确应用。这证明
通过这套架构,我们实现了企业级项目的终极目标:一套清晰、高效、可维护的样式体系,它完美平衡了全局一致性与组件独立性。
1.7 核心服务集成
一个应用不仅需要美观的 UI,还需要强大的 “内脏” 来处理数据请求、页面导航和状态管理。本节将为我们的项目集成这些核心服务,搭建起应用的 “神经与循环系统”。
当前任务: 1.7 - 核心服务集成
任务目标: 为项目安装并配置 Axios
(网络请求)、Vue Router
(路由)、Pinia
(客户端状态) 和 TanStack Query
(服务端状态)。
1.7.1 网络请求层 (Axios) 封装
在任何项目中,直接在组件中调用 axios.get(...)
都是一种不良实践。我们需要一个统一的、可配置的封装层来处理通用逻辑。
- 设计思路: 我们将创建一个
axios
实例,并配置通用的baseURL
和timeout
。更重要的是,我们将利用 拦截器 (Interceptors) 来实现:- 请求拦截器: 未来用于统一注入用户 token。
- 响应拦截器: 用于统一处理返回数据的结构(例如,直接返回
res.data
)和集中的错误处理(例如,401 未授权拦截)。
架构师,我们现在要开始做 API 请求了。我之前的习惯是在需要请求的组件里直接 import axios from 'axios'
然后就用了,这样做有什么问题吗?
这是一个很常见的起点,但在大型项目中会很快演变成一场灾难。想象一下,如果后端 API 的 baseURL 换了,或者所有请求都需要加一个统一的 header,你是不是得去几十个文件里一个个修改?
…好像是的,那维护成本太高了。
完全正确。所以,企业级项目的最佳实践,是创建一个全局的、封装好的 axios 实例。我们将所有的基础配置,比如 baseURL、超时时间,都放在这个文件里。更强大的是,我们可以用 “拦截器” 来打造请求的 “自动化流水线”。
“自动化流水线”?听起来很酷。
是的。比如,请求拦截器可以在每个请求发出去之前,自动检查并带上用户的 token。响应拦截器可以在收到数据后,自动帮架构师剥离掉外层的 data 包装,或者在遇到 401 这种通用错误时,直接弹出提示并跳转到登录页。这样架构师的业务组件就只需要关心业务本身了。
明白了!单一职责原则,让专业的工具做专业的事。那我们这个封装文件应该怎么写?
很好,你已经领悟到精髓了。我来给你提供一个非常标准的、具备良好扩展性的基础封装结构。
1. 依赖安装
1 | pnpm add axios |
2. 封装 HTTP 工具模块
在 src/utils/
目录下创建 http.ts
文件。
请将以下代码填入 src/utils/http.ts
文件中:
1 | // src/utils/http.ts |
代码解读:
axios.create
: 创建一个独立的 axios 实例,避免污染全局 axios。interceptors.request
: 在请求发送前进行拦截。我们在这里预留了未来添加 token 的逻辑。interceptors.response
: 在响应到达then/catch
之前进行拦截。我们在这里做了两件重要的事:- 成功回调中
res => res.data
,这可以让我们在后续调用时直接获取数据,无需再response.data
。 - 失败回调中预留了统一错误处理逻辑,例如 token 失效后的跳转登录页。
- 成功回调中
1.7.2 路由系统 (Vue Router)
Vue Router 是 Vue 官方的路由管理器,是构建单页应用 (SPA) 的标准配置。
1. 依赖安装
1 | pnpm add vue-router |
2. 创建路由配置文件
在 src/
目录下创建 router/index.ts
文件。
架构师,关于路由,我们这个电商项目页面还挺多的。比如有首页、登录页、分类页…我是不是应该给每个页面都创建一个顶级路由,比如 /
、/login
、/category
?
这是个好问题,它涉及到路由设计的核心思想。你看,首页和分类页,它们是不是都有共同的页头和页脚?
是的,都有。登录页没有。
这就是关键。我们会创建一个 Layout
组件,作为所有 “有公共布局” 页面的父级容器。然后,首页、分类页都作为它的 “子路由” 存在。当用户在这些页面间切换时,实际上只是 Layout
组件内部的一部分在变化,而页头页脚保持不变。这不仅代码复用性好,用户体验也更流畅。登录页则是一个独立的顶级路由。
原来如此!这就是嵌套路由的实际应用场景。那 path
该怎么写?首页的 path
应该是 /home
吗?
一个小技巧是,当 Layout
的 path
是 /
时,你可以给首页子路由一个空的 path: ''
。这样,访问根路径 /
时,就会自动渲染 Layout
并把首页作为它的默认内容。
明白了,这样设计清晰多了。
请将以下代码填入 src/router/index.ts
文件中,并根据需要创建对应的 .vue
文件 (可以先只写一个 <template><div>...</div></template>
):
1 | // src/router/index.ts |
代码解读:
createWebHistory
: 使用 H5 History 模式,URL 路径更美观。routes
: 路由规则数组。我们定义了一个 嵌套路由:/
路径会渲染Layout
组件,它作为所有一级页面的通用布局(包含导航、页头、页脚)。children
数组定义了二级路由。当访问/
时,由于path: ''
,会默认在Layout
组件的<RouterView />
中渲染Home
组件。
1.7.3 状态管理引擎安装与最终注册
最后,我们安装 Pinia
和 TanStack Query
,并在 main.ts
中完成所有核心服务的最终注册。
1. 依赖安装
1 | pnpm add pinia @tanstack/vue-query |
@tanstack/vue-query
的开发者工具 vue-query-devtools
在生产环境中不会被打包,但为了方便调试,推荐在开发依赖中安装它:pnpm add -D @tanstack/vue-query-devtools
。
2. 在 main.ts
中完成所有服务注册
这是我们 main.ts
文件的最终形态,它成为了所有核心服务的 “总装车间”。
1 | // src/main.ts |
1.8 API 自动导入优化
在【任务 1.3】中,我们已经为项目配置了路径别名,解决了深层相对路径的问题。本节,我们将解决另一个影响开发效率的痛点:在每个 Vue 组件中重复编写 import { ref, computed, ... } from 'vue'
。
当前任务: 1.8 - API 自动导入优化
任务目标: 配置 unplugin-auto-import
插件,实现对 Vue、Vue Router 等核心库 API 的自动导入,让开发者更专注于业务逻辑。
1.8.1 设计思路:解放 import
语句
unplugin-auto-import
插件的原理是在编译时扫描代码,如果发现你使用了像 ref
, computed
, onMounted
等未被导入的变量,它会自动检查这些变量是否属于预设库(如 ‘vue’, ‘vue-router’)的导出成员。如果是,它会自动为架构师添加导入语句。为了让 TypeScript 理解这些 “凭空出现” 的全局变量,该插件还会生成一个类型声明文件(.d.ts
)。
1.8.2 Vite 配置文件 (vite.config.ts
)
我们将扩展 unplugin-auto-import
的配置,明确告知它需要为哪些库开启自动导入。
架构师,路径别名确实方便多了。但现在我还是很烦,每个组件都要写一遍 import { ref, computed } from 'vue'
,有没有办法让它也自动化?
问得好,这正是我们要解决的下一个问题。专业的工作流,就是要消灭一切不必要的重复性劳动。unplugin-auto-import
这个插件,就是为此而生的。
之前我们安装 Element Plus 的时候已经装过它了。
是的,当时我们只用了它的基础功能。现在,我们要深入配置它,让它不仅处理 Element Plus 的 API,更能处理 Vue 和 Vue Router 的所有核心 API。我们还需要配置类型声明的生成路径,确保 TypeScript 和 IDE 能够正确识别这些 “凭空出现” 的全局变量。
明白了,这样我们就彻底告别手动 import 了!
完全正确!一旦配置完成,你在任何组件中都可以直接使用 ref
, computed
, useRouter
等 API,就像它们是全局变量一样自然。
现在,让我们扩展 vite.config.ts
中 unplugin-auto-import
的配置:
1 | // vite.config.ts |
配置解读:
imports: ['vue', 'vue-router']
: 我们明确告诉插件,自动扫描并导入vue
和vue-router
这两个库导出的所有 API。dts: 'src/auto-imports.d.ts'
: 这是至关重要的一步。插件会创建一个auto-imports.d.ts
文件,其中包含了所有自动导入 API 的 TypeScript 类型声明。
1.8.3 TypeScript 类型支持
我们需要确保 TypeScript 配置文件能够识别这个自动生成的类型声明文件。
在 tsconfig.app.json
文件中,确保 include
数组包含了 auto-imports.d.ts
:
1 | // tsconfig.app.json |
1.8.4 功能测试
现在,让我们创建一个测试组件来验证自动导入是否正常工作:
1 | <!-- src/components/AutoImportTest.vue --> |
重启 Vite 开发服务器后,如果上述代码能够正常运行且 VS Code 提供了完整的类型提示,说明自动导入配置成功!
配置成功标志: 当你输入 ref
、computed
等 API 时,VS Code 会自动提供智能提示,且无需手动导入即可正常使用。同时,你会发现项目根目录生成了 auto-imports.d.ts
文件。
最终完整的 vite.config.ts
1 | // vite.config.ts |
1.9 自动化提交流程
IDE 级别的配置能提升个人效率,但无法保证团队协作的一致性。我们需要在代码流入版本库的最后一道关卡——git commit
——设立 “自动化哨兵”,强制所有提交都遵循统一的质量和规范标准,确保代码仓库的纯净与专业。
当前任务: 1.9 - 自动化提交流程
任务目标: 初始化 Git 仓库并推送到 GitHub,然后集成 Husky
, lint-staged
, commitlint
,构建一个在提交代码前自动执行 “代码格式化”、“质量检查” 和 “提交信息规范校验” 的自动化工作流。
1.9.1 设计思路:三道防线
我们将建立三道质量防线:
- 第一道防线 - 预提交检查 (
pre-commit
Hook): 在git commit
执行前,自动对暂存区的文件运行ESLint
和Prettier
,确保所有即将提交的代码都符合质量和风格标准。 - 第二道防线 - 提交信息校验 (
commit-msg
Hook): 校验提交信息是否遵循约定式提交规范,确保提交历史的专业性和可读性。 - 第三道防线 - 推送前检查: 在推送到远程仓库前,可以添加额外的检查,如运行完整的测试套件。
1.9.2 Git 仓库初始化与远程连接
首先,我们需要为项目创建 Git 仓库并连接到远程仓库:
1 | # 1. 初始化 Git 仓库 |
1.9.3 依赖安装
现在安装所有自动化工具:
1 | pnpm add -D husky lint-staged @commitlint/cli @commitlint/config-conventional |
依赖解读:
包名 | 核心职责 |
---|---|
husky | Git Hooks 工具,让我们能轻松地在 pre-commit 、commit-msg 等 Git 事件上挂载自定义脚本。 |
lint-staged | 一个只对 Git 暂存区 内的文件执行任务的工具,极大地提升了检查效率。 |
@commitlint/cli | commitlint 的命令行工具,用于校验提交信息。 |
@commitlint/config-conventional | commitlint 的一个预设配置包,它规定了我们必须遵循 “约定式提交” 规范。 |
1.9.4 配置 Husky
与 lint-staged
(代码检查)
初始化
Husky
:1
pnpm exec husky init
配置
lint-staged
:
在package.json
中添加lint-staged
配置:1
2
3
4
5
6
7
8// package.json
{
// ... existing config
"lint-staged": {
"*.{js,jsx,ts,tsx,vue}": ["eslint --fix --cache", "prettier --write"],
"*.{json,md,scss,css}": ["prettier --write"]
}
}创建预提交钩子:
修改.husky/pre-commit
文件:1
2# .husky/pre-commit
npx lint-staged
工作原理解读:
lint-staged
只会对 Git 暂存区(git add
后的文件)执行检查,大大提升了性能。- 对于 JS/TS/Vue 文件,先运行
eslint --fix
自动修复问题,再用prettier
统一格式。 - 对于配置文件和文档,只运行
prettier
格式化。
1.9.5 配置 commitlint
(提交信息规范)
约定式提交规范说明:
我们要求所有提交信息都遵循type(scope): subject
的格式。这不仅使提交历史清晰可读,更是自动化生成CHANGELOG
和版本管理的基础。类型 ( type
)含义 feat
新增功能 fix
修复 Bug docs
文档变更 style
代码风格调整(不影响逻辑) refactor
代码重构 perf
性能优化 test
新增或修改测试 chore
构建流程、辅助工具的变更 创建
commitlint.config.js
:
在项目根目录创建配置文件:1
2
3
4// commitlint.config.js
export default {
extends: ["@commitlint/config-conventional"],
};创建提交信息钩子:
创建.husky/commit-msg
文件:1
2# .husky/commit-msg
npx --no-install commitlint --edit $1
1.9.6 添加便捷脚本
为了方便开发,在 package.json
中添加一些实用的脚本:
1 | // package.json |
1.9.7 完整测试流程
现在让我们测试整个自动化工作流是否正常:
故意制造一些格式问题: 在任意
.vue
文件中添加一些不规范的代码(如缺少分号、不一致的引号等)。测试预提交检查:
1
2git add .
git commit -m "test commit"你应该看到
lint-staged
自动运行,修复代码格式问题。测试提交信息校验:
执行一次 不符合规范 的提交:
git commit -m "test"
。- 预期结果: 终端会提示
subject may not be empty, type may not be empty
等错误,提交被 中止。
执行一次 符合规范 的提交:
git commit -m "feat: setup automated commit workflow"
。- 预期结果:
lint-staged
首先运行,你会看到eslint
和prettier
的输出,格式问题被自动修复。commitlint
校验通过。提交成功!
- 预期结果: 终端会提示
成功标志: 当你能够成功提交一个符合规范的 commit,并且在过程中看到代码被自动格式化,说明整个自动化提交流程已经完美搭建完成!