在跨端开发日益成为主流的今天,如何高效构建规范、可维护的企业级应用?本文以UniApp+Vue3+* *TypeScript**为核心技术栈,手把手带你从零搭建高标准的跨平台项目。
通过本文,你将系统掌握:
- ✅ 环境配置:Node版本管理、Vite脚手架初始化、Vue3+TS工程化配置
- ✅ 开发规范:ESLint+Prettier+Stylelint三剑客整合,Git提交自动化与Commitizen规范化
- ✅ 进阶实战:Pinia全局状态管理、UnoCSS原子化样式、HTTP请求封装与反向代理实战
- ✅ 工程扩展:UI库深度整合(uView-plus/wot-design-uni)、按需自动导入、多环境变量策略
- ✅ 跨端适配:H5/小程序多平台编译与Nginx部署方案,破解跨域难题
无论你是初探UniApp生态,还是希望升级现有项目的工程化水平,本文都将提供从环境搭建到生产部署的全链路指南,助你打造高性能、高规范、跨端兼容的现代Web应用。代码即规范,开箱即用,开启高效开发之旅!
Gitee开源地址: https://gitee.com/moxunjinmu/uniapp-vue3-template
Github开源地址:https://github.com/moxunjinmu/uniapp-vue3-template
如果对你有点用的话欢迎Star✨✨✨,拜托啦~
一、环境准备
安装Node.js(推荐nvm安装管理node版本)
👉 NVM (Node Version Manager) 是一个用于管理多个 Node.js 版本的工具,便于在不同项目间切换 Node 环境
详细安装教程:莫循跃迁:nvm管理node版本速通👉 nvm(Node Version Manager)是一个用于管理Node.js - 掘金
配置效果
安装完成后,可以通过以下命令验证:
nvm -v
注意事项
- 推荐使用 Node.js 16.x 或更高版本
- 在 Windows 系统中,可能需要以管理员身份运行命令提示符
安装开发工具
安装VScode
👉 Visual Studio Code 是微软开发的轻量级代码编辑器,支持多种编程语言和丰富的插件扩展
下载地址:https://code.visualstudio.com/
或者安装cursor
👉 Cursor 是一款基于 AI 的代码编辑器,提供智能代码补全和建议功能
详细安装教程:《AI编程开发微信小程序》第一章:AI自动化编程神器Cursor基础使用教程嗨,大家好,我是莫循,一个用AI加速开发的 - 掘金
安装Vue CLI
👉 Vue CLI 是 Vue.js 官方提供的项目脚手架工具,用于快速创建和配置 Vue 项目
全局安装
npm install -g @vue/cli # 默认安装最新版
权限问题:
- Windows:以管理员身份运行 CMD 或 PowerShell
- Linux/Mac:添加
sudo
前缀(sudo npm install -g @vue/cli
)
验证安装
vue --version # 显示版本号如 @vue/cli 5.0.8
常见错误:
'vue' 不是内部命令
:检查环境变量是否包含npm
全局路径(默认:C:\Users<用户>\AppData\Roaming\npm
)- 版本过低:通过
npm update -g @vue/cli
升级
二、创建项目
初始化项目
👉 按照 uni-app 官方文档 的步骤,通过 vue-cli
创建 uni-app
+ vue
+ typescript
脚手架:
npx degit dcloudio/uni-preset-vue#vite-ts uniapp-vue3-template
⚠️ 如果使用命令创建失败,可以通过 Gitee 下载 ZIP 包:vite-ts 分支。
配置TypeScript
编译器
👉 TypeScript 编译器配置文件决定了代码的编译规则和类型检查行为
默认生成的 TypeScript
编译器配置文件 tsconfig.json
中继承的 @vue/tsconfig/tsconfig.json
文件不存在。因此,你需要移除此继承配置并添加相应的编译设置。
根据 TypeScript 官方配置文档,调整后的完整配置如下:
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"target": "esnext",
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"sourceMap": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"lib": ["esnext", "dom"],
"types": ["@dcloudio/types", "vue"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"exclude": ["node_modules", "dist"]
}
正确配置后,TypeScript 编译器将能够:
- 识别 @/* 路径别名
- 提供 Vue 和 uni-app 的类型支持
- 对项目中的 .ts 和 .vue 文件进行类型检查 注意事项
- 确保 types 数组中包含 @dcloudio/types 和 vue ,以获得完整的类型支持
- 如果遇到类型错误,可能需要安装相应的类型定义包: npm install --save-dev @dcloudio/types @vue/runtime-core
三、核心配置
代码规范配置
配置ESLint
👉 ESLint 是一个静态代码分析工具,用于识别和报告 JavaScript/TypeScript 代码中的问题
VSCode 插件市场搜索 ESLint 插件并安装
安装插件
VSCode 插件市场搜索 ESLint 插件并安装
通过以下命令快速生成 ESLint 配置文件:
npx eslint --init
配置过程
PS D:\700-code\750-Gitee\uniapp-vue3-template> npx eslint --init
You can also run this command directly using 'npm init @eslint/config@latest'.
@eslint/create-config: v1.6.0
√ How would you like to use ESLint? · problems
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ What type of modules does your project use? · esm
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ What type of modules does your project use? · esm
√ What type of modules does your project use? · esm
√ Which framework does your project use? · vue
√ Does your project use TypeScript? · typescript
√ Does your project use TypeScript? · typescript
√ Where does your code run? · browser
√ Where does your code run? · browser
The config that you've selected requires the following dependencies:
The config that you've selected requires the following dependencies:
eslint, globals, @eslint/js, typescript-eslint, eslint-plugin-vue
eslint, globals, @eslint/js, typescript-eslint, eslint-plugin-vue
√ Would you like to install them now? · No / Yes
√ Would you like to install them now? · No / Yes
√ Which package manager do you want to use? · pnpm
√ Which package manager do you want to use? · pnpm
☕️Installing...
☕️Installing...
WARN 7 deprecated subdependencies found: abab@2.0.6, domexception@2.0.1, glob@7.2.3, inflight@1.0.6, phin@2.9.3, rimraf@3.0.2, w3c-hr-time@1.0.2
Packages: +72
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 863, reused 790, downloaded 32, added 72, done
WARN Issues with peer dependencies found
.
└─┬ @dcloudio/uni-automator 3.0.0-4030620241128001
└─┬ @dcloudio/uni-cli-shared 3.0.0-4030620241128001
└─┬ @vue/server-renderer 3.4.21
└── ✕ unmet peer vue@3.4.21: found 3.5.13
devDependencies:
+ @eslint/js 9.23.0
+ eslint 9.23.0
+ eslint-plugin-vue 10.0.0
+ globals 16.0.0
+ typescript-eslint 8.27.0
Done in 6.1s
Done in 6.1s
Successfully created D:\700-code\750-Gitee\uniapp-vue3-template\eslint.config.mjs file.
执行该命令后,ESLint 会通过交互式问题的方式,帮助生成配置文件。针对 9.x 版本,默认会生成基于 Flat Config 格式的 eslint.config.mjs
文件,与之前的 .eslintrc
格式有所不同。
默认生成的 eslint.config.mjs
文件如下所示:
在此基础上,可以根据项目的需求进行一些定制化配置,例如添加忽略规则或自定义的特殊规则。
import globals from "globals"; // 全局变量配置
import pluginJs from "@eslint/js"; // JavaScript 的推荐配置
import tseslint from "typescript-eslint"; // TypeScript 配置
import pluginVue from "eslint-plugin-vue"; // Vue 配置
export default [
{files: ["**/*.{js,mjs,cjs,ts,vue}"]}, // 校验的文件类型
{languageOptions: { globals: {...globals.browser , ...globals.node} }}, // 浏览器/Node环境全局变量
pluginJs.configs.recommended, // JavaScript 推荐配置
...tseslint.configs.recommended, // TypeScript 推荐配置
...pluginVue.configs["flat/essential"], // Vue 推荐配置
{ files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } }, // 对 .vue 文件使用 TypeScript 解析器
// 添加忽略的文件或目录
{
ignores: [
"/dist",
"/public",
"/node_modules",
"**/*.min.js",
"**/*.config.mjs",
"**/*.tsbuildinfo",
"/src/manifest.json",
]
},
// 自定义规则
{
rules: {
quotes: ["error", "double"], // 强制使用双引号
"quote-props": ["error", "always"], // 强制对象的属性名使用引号
semi: ["error", "always"], // 要求使用分号
indent: ["error", 2], // 使用两个空格进行缩进
"no-multiple-empty-lines": ["error", { max: 1 }], // 不允许多个空行
"no-trailing-spaces": "error", // 不允许行尾有空格
// TypeScript 规则
"@typescript-eslint/no-explicit-any": "off", // 禁用 no-explicit-any 规则,允许使用 any 类型
"@typescript-eslint/explicit-function-return-type": "off", // 不强制要求函数必须明确返回类型
"@typescript-eslint/no-empty-interface": "off", // 禁用 no-empty-interface 规则,允许空接口声明
"@typescript-eslint/no-empty-object-type": "off", // 允许空对象类型
// Vue 规则
"vue/multi-word-component-names": "off", // 关闭多单词组件名称的限制
"vue/html-indent": ["error", 2], // Vue 模板中的 HTML 缩进使用两个空格
"vue/no-v-html": "off", // 允许使用 v-html (根据实际项目需要)
},
},
];
添加 ESLint 脚本
👉 在 package.json 中添加 lint 命令,方便执行代码检查
为了方便使用 ESLint,可以在 package.json
中添加 lint
脚本命令:
{
"scripts": {
"lint:eslint": "eslint --fix ./src",
"lint": "npm run lint:eslint"
}
}
此脚本会自动修复符合 ESLint 规则的代码问题,并输出检查结果。
测试效果
在 App.vue
文件中声明一个未使用的变量,并运行 pnpm run lint
,可以看到 ESLint 提示该变量未使用。如下图所示:
这里多报了一个错误显示 ‘@typescript-eslint/ban-types’ was not found,查找解决方法,需要安装依赖。我们执行下方命令:
> npm install --save-dev @typescript-eslint/eslint-plugin @typescript-eslint/parser
重新执行pnpm run lint ,结果:
安装解析器
👉 vue-eslint-parser 是专门用于解析 .vue 文件的 ESLint 解析器
pnpm install vue-eslint-parser --save-dev
针对不同文件配置插件和解析器:
// eslint.config.mjs
import globals from "globals";
import js from "@eslint/js";
// ESLint 核心插件
import pluginVue from "eslint-plugin-vue";
import pluginTypeScript from "@typescript-eslint/eslint-plugin";
// Prettier 插件及配置
import configPrettier from "eslint-config-prettier";
import pluginPrettier from "eslint-plugin-prettier";
// 解析器
import * as parserVue from "vue-eslint-parser";
import * as parserTypeScript from "@typescript-eslint/parser";
// 定义 ESLint 配置
export default [
// 通用 JavaScript/TypeScript 配置
{
...js.configs.recommended,
ignores: [
"/dist",
"/public",
"/node_modules",
"**/*.min.js",
"**/*.config.mjs",
"**/*.tsbuildinfo",
"/src/manifest.json",
],
languageOptions: {
globals: {
...globals.browser, // 浏览器变量 (window, document 等)
...globals.node, // Node.js 变量 (process, require 等)
},
},
plugins: {
prettier: pluginPrettier,
},
rules: {
...configPrettier.rules,
...pluginPrettier.configs.recommended.rules,
"no-debug": "off", // 允许使用 debugger
"prettier/prettier": [
"error",
{
endOfLine: "auto", // 解决换行符冲突
},
],
},
},
// TypeScript 配置
{
files: ["**/*.?([cm])ts"],
languageOptions: {
parser: parserTypeScript,
parserOptions: {
sourceType: "module",
},
},
plugins: {
"@typescript-eslint": pluginTypeScript,
},
rules: {
...pluginTypeScript.configs.recommended.rules,
"@typescript-eslint/no-explicit-any": "off", // 允许使用 any
"@typescript-eslint/no-empty-function": "off", // 允许空函数
"@typescript-eslint/no-empty-object-type": "off", // 允许空对象类型
"@typescript-eslint/consistent-type-imports": [
"error",
{ disallowTypeAnnotations: false, fixStyle: "inline-type-imports" },
], // 统一类型导入风格
},
},
// TypeScript 声明文件的特殊配置
{
files: ["**/*.d.ts"],
rules: {
"eslint-comments/no-unlimited-disable": "off", // 关闭 eslint 注释相关规则
"unused-imports/no-unused-vars": "off", // 忽略未使用的导入
},
},
// JavaScript (commonjs) 配置
{
files: ["**/*.?([cm])js"],
rules: {
"@typescript-eslint/no-var-requires": "off", // 允许 require
},
},
// Vue 文件配置
{
files: ["**/*.vue"],
languageOptions: {
parser: parserVue,
parserOptions: {
parser: "@typescript-eslint/parser",
sourceType: "module",
},
},
plugins: {
vue: pluginVue,
},
processor: pluginVue.processors[".vue"],
rules: {
...pluginVue.configs["vue3-recommended"].rules,
"vue/no-v-html": "off", // 允许 v-html
"vue/require-default-prop": "off", // 允许没有默认值的 prop
"vue/multi-word-component-names": "off", // 关闭组件名称多词要求
"vue/html-self-closing": [
"error",
{
html: { void: "always", normal: "always", component: "always" },
svg: "always",
math: "always",
},
], // 自闭合标签
},
},
];
集成 Prettier
👉 Prettier 是一个代码格式化工具,可以强制执行一致的代码风格
prettier 中文网:https://prettier.nodejs.cn/
安装插件
VSCode 插件市场搜索 Prettier - Code formatter
插件安装
安装依赖
pnpm install -D prettier eslint-config-prettier eslint-plugin-prettier
- prettier:主要的 Prettier 格式化库。
- eslint-plugin-prettier:将 Prettier 的规则作为 ESLint 的规则来运行。
- eslint-config-prettier:禁用所有与格式相关的 ESLint 规则,以避免和 Prettier 的冲突。
配置 Prettier
👉 以下是 Prettier 配置文件,定义了代码格式化的规则
项目根目录下新建配置文件 prettier.config.mjs
,添加常用规则:
export default {
printWidth: 100, // 每行最多字符数量,超出换行(默认80)
tabWidth: 2, // 缩进空格数,默认2个空格
useTabs: false, // 指定缩进方式,空格或tab,默认false,即使用空格
semi: true, // 使用分号
singleQuote: false, // 使用单引号 (true:单引号;false:双引号)
trailingComma: 'all', // 末尾使用逗号
};
配置忽略文件
项目根目录新建 .prettierignore
文件指定 Prettier 不需要格式化的文件和文件夹
.prettierignore
node_modules
dist
public
*.min.js
添加格式化脚本
在 package.json
文件中添加:
{
"scripts": {
"format": "prettier --write ./src"
}
}
保存自动格式化
打开 VSCode 的 File
→ Preferences
→ Settings
,然后选择 Open Settings (JSON)
,添加以下配置
{
"editor.formatOnSave": true, // 保存格式化文件
"editor.defaultFormatter": "esbenp.prettier-vscode" // 指定 prettier 为所有文件默认格式化器
}
集成 Stylelint
👉 Stylelint 一个强大的 CSS linter(检查器),可帮助您避免错误并强制执行约定。
Stylelint 官网:https://stylelint.io/
安装插件
VSCode 插件搜索 Stylelint
并安装
安装依赖
pnpm install -D postcss postcss-html postcss-scss stylelint stylelint-config-recommended stylelint-config-recommended-scss stylelint-config-recommended-vue stylelint-config-recess-order stylelint-config-html stylelint-prettier
表格 还在加载中,请等待加载完成后再尝试复制
配置 Stylelint
根目录新建 .stylelintrc.cjs
文件,配置如下:
module.exports = {
extends: [
"stylelint-config-recommended",
"stylelint-config-recommended-scss",
"stylelint-config-recommended-vue/scss",
"stylelint-config-html/vue",
"stylelint-config-recess-order"
],
plugins: ["stylelint-prettier"],
overrides: [
{
files: ["**/*.{vue,html}"],
customSyntax: "postcss-html"
},
{
files: ["**/*.{css,scss}"],
customSyntax: "postcss-scss"
}
],
rules: {
"import-notation": "string",
"selector-class-pattern": null,
"custom-property-pattern": null,
"keyframes-name-pattern": null,
"no-descending-specificity": null,
"no-empty-source": null,
"selector-pseudo-class-no-unknown": [
true,
{
ignorePseudoClasses: ["global", "export", "deep"]
}
],
"unit-no-unknown": [
true,
{
ignoreUnits: ["rpx"]
}
],
"property-no-unknown": [
true,
{
ignoreProperties: []
}
],
"at-rule-no-unknown": [
true,
{
ignoreAtRules: ["apply", "use", "forward"]
}
]
}
};
配置忽略文件
根目录创建 .stylelintignore 文件,配置忽略文件如下:
*.min.js
dist
public
node_modules
添加 Stylelint 脚本
package.json 添加 Stylelint 检测指令:
"scripts": {
"lint:stylelint": "stylelint "**/*.{css,scss,vue,html}" --fix"
}
保存自动修复
项目根目录下.vscode/settings.json
文件添加配置:
{
"editor.codeActionsOnSave": {
"source.fixAll.stylelint": true
},
"stylelint.validate": ["css", "scss", "vue", "html"]
}
为了验证把尺寸属性 width 放置在定位属性 position 前面,根据 CSS 书写顺序规范 推断是不符合规范的,在保存时 Stylelint 自动将属性重新排序,达到预期。
测试
执行以下命令进行检测
npm run lint:stylelint
Git提交规范配置
👉 配置 Husky 的 pre-commit
和 commit-msg
钩子,实现代码提交的自动化检查和规范化。
- pre-commit: 使用 Husky + Lint-staged,在提交前进行代码规范检测和格式化。确保项目已配置 ESLint、Prettier 和 Stylelint。
- commit-msg: 结合 Husky、Commitlint、Commitizen 和 cz-git,生成规范化且自定义的 Git commit 信息。
集成 Husky
👉 Husky 是 Git 钩子工具,可以设置在 git 各个阶段(pre-commit
、commit-msg
等)触发。
Husky官网:https://typicode.github.io
安装依赖
pnpm add -D husky
初始化
init
命令简化了项目中的 husky 设置。它会在 .husky/
中创建 pre-commit
脚本,并更新 package.json
中的 prepare
脚本。
pnpm exec husky init
默认生成了 pnpm test ,改成 echo "Running pre-commit hook..."
测试功能
echo "Running pre-commit hook..."
测试
通过 pre-commit
钩子,可以自动运行各种代码检查工具,在提交代码前强制执行代码质量和样式检查。常见的工具包括:
eslint
:用于检查和修复 JavaScript/TypeScript 代码中的问题。stylelint
:用于检测和修复 CSS/SCSS 样式问题。
接下来,集成 lint-staged
和 commitlint
来进一步完善开发体验。
集成 lint-staged
👉 lint-staged
是一个工具,专门用于只对 Git 暂存区的文件运行 lint 或其他任务,确保只检查和修复被修改或新增的代码部分,而不会影响整个代码库。这样可以显著提升效率,尤其是对于大型项目。
安装依赖
使用以下命令安装 lint-staged
:
pnpm add -D lint-staged
配置 lint-staged
在 package.json
中添加 lint-staged
配置,确保在 pre-commit
阶段自动检测暂存的文件:
{
"name": "vue-uniapp-template",
"version": "0.0.0",
"lint-staged": {
"*.{js,ts}": [
"eslint --fix",
"prettier --write"
],
"*.{cjs,json}": [
"prettier --write"
],
"*.{vue,html}": [
"eslint --fix",
"prettier --write",
"stylelint --fix"
],
"*.{scss,css}": [
"stylelint --fix",
"prettier --write"
],
"*.md": [
"prettier --write"
]
}
}
在 package.json
的 scripts
部分中,添加用于运行 lint-staged
的命令:
"scripts": {
"lint:lint-staged": "lint-staged"
}
添加 Husky 钩子
在项目根目录的 .husky/pre-commit
中添加以下命令,确保在提交代码前执行 lint-staged
:
pnpm run lint:lint-staged
测试
提交代码时,lint-staged
会自动对暂存的文件运行相应的 lint 任务。
通过这种集成方式,确保代码在提交前经过自动格式化和校验,提高代码质量和一致性。
集成 Commitlint
👉 commitlint
用于检查 Git 提交信息是否符合特定规范(如 Angular 提交规范),从而保证提交信息的一致性。
Commitlint官网:https://commitlint.js.org/
安装依赖
pnpm add -D @commitlint/cli @commitlint/config-conventional
配置 Commitlint
在项目根目录下创建 commitlint.config.cjs
文件,添加以下内容来启用 Angular 规范:
module.exports = {
// 继承的规则
extends: ["@commitlint/config-conventional"],
// 自定义规则
rules: {
// 提交类型枚举,git提交type必须是以下类型 @see https://commitlint.js.org/#/reference-rules
"type-enum": [
2,
"always",
[
"feat", // 新增功能
"fix", // 修复缺陷
"docs", // 文档变更
"style", // 代码格式(不影响功能,例如空格、分号等格式修正)
"refactor", // 代码重构(不包括 bug 修复、功能新增)
"perf", // 性能优化
"test", // 添加疏漏测试或已有测试改动
"build", // 构建流程、外部依赖变更(如升级 npm 包、修改 webpack 配置等)
"ci", // 修改 CI 配置、脚本
"revert", // 回滚 commit
"chore", // 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)
],
],
"subject-case": [0], // subject大小写不做校验
},
};
添加 Husky 钩子
将 commitlint
与 Husky 集成,在 .husky/commit-msg
文件中添加以下内容,确保提交信息符合规范:
npx --no-install commitlint --edit $1
测试
根据 Angular 的提交规范,提交信息由以下部分组成:
- 类型:表示本次提交的类型,例如
feat
(新功能)、fix
(修复 bug)、docs
(文档更新)。 - 作用域(可选):说明本次提交影响的模块,例如
auth
、ui
。 - 简短描述:简洁明了的提交描述,限定在 50 字符以内。
当你尝试提交不符合规范的提交信息时,提交会被阻止,并显示相关错误提示。如下图所示:
集成 Commitizen 和 cz-git
- commitizen: 是一个帮助开发者以标准化格式生成提交信息的工具。–Commitizen 官方文档
- cz-git:
cz-git
是Commitizen
的适配器之一,它基于Commitizen
,提供了更多自定义功能和增强的交互体验。–cz-git 官方文档
安装依赖
配置 cz-git
在项目中初始化 Commitizen
,并配置使用 cz-git
作为适配器。在 package.json
中添加以下配置:
"config": {
"commitizen": {
"path": "node_modules/cz-git"
}
}
在commitlint
的配置文件 commitlint.config.cjs
中添加配置,commitlint 配置模板:https://cz-git.qbb.sh/zh/config/
module.exports = {
// 继承的规则
extends: ["@commitlint/config-conventional"],
// 自定义规则
rules: {
// ......
// cz-git 配置
prompt: {
messages: {
type: "选择你要提交的类型 :",
scope: "选择一个提交范围(可选):",
customScope: "请输入自定义的提交范围 :",
subject: "填写简短精炼的变更描述 :\n",
body: "填写更加详细的变更描述(可选)。使用 "|" 换行 :\n",
breaking: "列举非兼容性重大的变更(可选)。使用 "|" 换行 :\n",
footerPrefixesSelect: "选择关联issue前缀(可选):",
customFooterPrefix: "输入自定义issue前缀 :",
footer: "列举关联issue (可选) 例如: #31, #I3244 :\n",
generatingByAI: "正在通过 AI 生成你的提交简短描述...",
generatedSelectByAI: "选择一个 AI 生成的简短描述:",
confirmCommit: "是否提交或修改commit ?",
},
// prettier-ignore
types: [
{ value: "feat", name: "特性: ✨ 新增功能", emoji: ":sparkles:" },
{ value: "fix", name: "修复: 🐛 修复缺陷", emoji: ":bug:" },
{ value: "docs", name: "文档: 📝 文档变更", emoji: ":memo:" },
{ value: "style", name: "格式: 💄 代码格式(不影响功能,例如空格、分号等格式修正)", emoji: ":lipstick:" },
{ value: "refactor", name: "重构: ♻️ 代码重构(不包括 bug 修复、功能新增)", emoji: ":recycle:" },
{ value: "perf", name: "性能: ⚡️ 性能优化", emoji: ":zap:" },
{ value: "test", name: "测试: ✅ 添加疏漏测试或已有测试改动", emoji: ":white_check_mark:"},
{ value: "build", name: "构建: 📦️ 构建流程、外部依赖变更(如升级 npm 包、修改 vite 配置等)", emoji: ":package:"},
{ value: "ci", name: "集成: 🎡 修改 CI 配置、脚本", emoji: ":ferris_wheel:"},
{ value: "revert", name: "回退: ⏪️ 回滚 commit",emoji: ":rewind:"},
{ value: "chore", name: "其他: 🔨 对构建过程或辅助工具和库的更改(不影响源文件、测试用例)", emoji: ":hammer:"},
],
useEmoji: true,
emojiAlign: "center",
useAI: false,
aiNumber: 1,
themeColorCode: "",
scopes: [],
allowCustomScopes: true,
allowEmptyScopes: true,
customScopesAlign: "bottom",
customScopesAlias: "custom",
emptyScopesAlias: "empty",
upperCaseSubject: false,
markBreakingChangeMode: false,
allowBreakingChanges: ["feat", "fix"],
breaklineNumber: 100,
breaklineChar: "|",
skipQuestions: [],
issuePrefixes: [{ value: "closed", name: "closed: ISSUES has been processed" }],
customIssuePrefixAlign: "top",
emptyIssuePrefixAlias: "skip",
customIssuePrefixAlias: "custom",
allowCustomIssuePrefix: true,
allowEmptyIssuePrefix: true,
confirmColorize: true,
maxHeaderLength: Infinity,
maxSubjectLength: Infinity,
minSubjectLength: 0,
scopeOverrides: undefined,
defaultBody: "",
defaultIssues: "",
defaultScope: "",
defaultSubject: "",
},
};
添加 cz-git 脚本
在package.json
文件中添加 commit
脚本命令
"scripts": {
"commit": "git-cz"
}
测试
先添加git add
执行 pnpm run commit
命令后,按照提示输入相关信息,最终生成符合规范的提交信息。
样式处理
添加sass
👉 Sass是帮助开发者编写、管理和维护样式的强大工具,通过 <style lang="scss">
使用。它提供变量、嵌套、混合等功能,提升了样式的可维护性和开发效率,尤其在复杂项目中减少重复代码、提高复用性。
pnpm add -D sass sass-loader
四、功能实现
UnoCSS 原子化样式
👉 UnoCSS 是一个高性能、灵活且按需生成的原子化 CSS 引擎。
官方网站:https://unocss.net/
先比较下
内部样式
UnoCSS原子样式
安装插件
👉 VSCode
安装 UnoCSS
插件
安装依赖
本次整合基于官网提供的社区预设 unocss-preset-weapp。该预设内置了 transformer
,用于解决小程序的兼容性问题。
进一步参考 unocss-preset-weapp 的 uniapp_vue3 使用与配置指南,使用以下命令安装 UnoCSS 和 unocss-preset-weapp
:
pnpm add -D unocss unocss-preset-weapp
配置 UnoCSS
👉 参考 unocss-preset-weapp 的 uniapp_vue3 使用与配置指南,配置如下:
vite.config.ts
import { defineConfig } from "vite"; import uni from "@dcloudio/vite-plugin-uni"; export default defineConfig(async () => { const UnoCss = await import("unocss/vite").then(i => i.default); return { "plugins": [ uni(), // 配置 UnoCSS UnoCss(), ], }; });
unocss.config.ts
- 添加unocss.config.ts文件,搭配 unocss vscode 插件,智能提示
import { presetWeapp } from "unocss-preset-weapp"; import { extractorAttributify, transformerClass } from "unocss-preset-weapp/transformer"; const { presetWeappAttributify, transformerAttributify } = extractorAttributify(); export default { "presets": [ // https://github.com/MellowCo/unocss-preset-weapp presetWeapp(), // attributify autocomplete presetWeappAttributify(), ], "shortcuts": [ { "flex-center": "flex justify-center items-center", "flex-col": "flex flex-col", }, ], "transformers": [ // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerAttributify transformerAttributify(), // https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClass transformerClass(), ], };
shortcuts
自定义样式组合:可以在shortcuts
中定义常用的样式组合,以便简化项目中的样式使用和维护,避免冗余和重复的样式。
main.ts
import 'uno.css'
测试
下图展示了在 VSCode 中测试 UnoCSS 时,智能提示和样式设置功能已经正常生效。
此外,在 unocss.config.ts
文件中预设的 shortcuts
组合样式也得到了正确应用。
TabBar 导航
👉 在 APP 开发中,底部导航栏(TabBar)是移动端应用的重要部分,方便用户在不同页面间进行切换。
添加页面
在初始化的模板项目中,src/pages
目录下默认有一个 index/index.vue
页面。为了更好地演示 TabBar
的切换效果,我们在 pages
目录下再新增两个页面:
- 首页(
src/pages/home/index.vue
):
<template>
<view class="flex-center flex-col">
<view>
<text class="text-cyan font-bold text-lg">工作台</text>
</view>
</view>
</template>
- 我的(
src/pages/profile/index.vue
):
<template>
<view class="flex-center flex-col">
<view>
<text class="text-blue font-bold text-lg">我的</text>
</view>
</view>
</template>
添加图标
在 src/static
目录下创建一个 tabbar
文件夹,存放从 iconfont 获取的图标。每个图标都需要有未激活和激活两种状态的样式。
配置 TabBar
在 UniApp 项目中,底部导航栏(TabBar)通过配置 pages.json
文件来实现。首先,找到并打开项目根目录下的 src/pages.json
文件。在该文件中,可以为每个页面配置导航栏,同时定义 TabBar。
下面是完整的配置示例,注意 tabBar
中的 pagePath
必须对应 pages
目录下的实际页面路径。
{
"pages": [
//pages数组中第一项表示应用启动页,参考:https://uniapp.dcloud.io/collocation/pages
{
"path": "pages/index/index",
"style": {
"navigationBarTitleText": "首页"
}
},
{
"path": "pages/history/index",
"style": {
"navigationBarTitleText": "历史"
}
},
{
"path": "pages/profile/index",
"style": {
"navigationBarTitleText": "我的"
}
}
],
"globalStyle": {
"navigationBarTextStyle": "black",
"navigationBarTitleText": "uni-app",
"navigationBarBackgroundColor": "#F8F8F8",
"backgroundColor": "#F8F8F8"
},
"tabBar": {
"color": "#8C8C8C",
"selectedColor": "#4080FF",
"backgroundColor": "#FFFFFF",
"borderStyle": "black",
"list": [
{
"pagePath": "pages/index/index",
"text": "首页",
"iconPath": "static/tabbar/home.png",
"selectedIconPath": "static/tabbar/home-active.png"
},
{
"pagePath": "pages/history/index",
"text": "历史",
"iconPath": "static/tabbar/history.png",
"selectedIconPath": "static/tabbar/history-active.png"
},
{
"pagePath": "pages/profile/index",
"text": "我的",
"iconPath": "static/tabbar/profile.png",
"selectedIconPath": "static/tabbar/profile-active.png"
}
]
}
}
按需自动导入
👉 自动导入API和组件库
在传统的 Vue 开发中,我们通常需要在每个页面手动导入 Vue 组合式 API(如 ref
, reactive
, onMounted
等)。随着项目的增大,手动导入会增加代码的冗余度,降低开发体验。
通过对比,来看一下手动导入与按需自动导入的区别:
手动导入
按需自动导入
手动导入: 每个页面都需要显式地引入 ref
, reactive
, onMounted
等组合式 API。 按需自动导入: 配置了自动导入插件后,这些 API 无需显式导入即可直接使用,减少了重复代码,提高了开发效率。
由于当前还未整合按需自动导入插件,所以右图的代码仍然报错,提示未找到 ref
和 reactive
的定义。这展示了按需自动导入的重要性:一旦整合插件,这类错误将被消除,代码更加简洁易维护。
安装依赖
首先使用以下命令安装 unplugin-auto-import
插件:
pnpm add -D unplugin-auto-import
配置自动导入
接着,在 vite.config.ts
中配置 unplugin-auto-import
插件,确保 Vue 和 UniApp 的 API 能够自动按需导入。
// vite.config.ts
import { defineConfig } from "vite";
import uni from "@dcloudio/vite-plugin-uni";
import AutoImport from "unplugin-auto-import/vite";
export default defineConfig(async () => {
const UnoCss = await import("unocss/vite").then(i => i.default);
return {
"plugins": [
uni(),
// 配置 UnoCSS
UnoCss(),
AutoImport({
"imports": ["vue", "uni-app"], // 自动导入 Vue 和 UniApp 的 API
"dts": "src/types/auto-imports.d.ts", // 自动生成类型声明文件
"eslintrc": {
"enabled": true, // 生成 ESLint 配置文件
"filepath": "./.eslintrc-auto-import.json", // ESLint 配置文件路径
},
}),
],
};
});
性能对比
配置 ESLint 规则
👉 ESLint 是一个可配置的 JavaScript/TypeScript 代码检查工具,用于发现并修复代码中的错误、风格问题和潜在缺陷。
为了让 ESLint 能识别这些通过 unplugin-auto-import
自动导入的 API,需要在 ESLint 的配置中引入 unplugin-auto-import
生成的 .eslintrc-auto-import.json
文件。
在 ESLint 9.x 版本中,使用 Flat Config 时不再支持 extends
关键字。因此,不能使用以下配置:
// 错误示例
export default [
{
extends: ["./.eslintrc-auto-import.json"], // 这种扩展方式在 Flat Config 中不再支持
},
];
取而代之的是直接引入 .eslintrc-auto-import.json
文件内容,通过解析文件的方式将自动导入的全局变量配置整合进 ESLint 配置。
在 eslint.config.mjs
中添加如下配置:
// eslint.config.mjs 正确的配置
import { readFileSync } from "fs";
import { fileURLToPath } from "url";
import { dirname, resolve } from "path";
// 动态读取 .eslintrc-auto-import.json 文件内容
const autoImportConfig = JSON.parse(
readFileSync(
resolve(dirname(fileURLToPath(import.meta.url)), ".eslintrc-auto-import.json"),
"utf-8",
),
);
export default [
{
// 语言选项配置,定义全局变量
languageOptions: {
globals: {
// ...
...autoImportConfig.globals, // 自动导入的全局变量
},
},
},
];
这样配置后,ESLint 将能够识别通过自动导入的 API,避免例如 'ref' is not defined
这样的错误,从而使项目的开发更加顺畅。
配置Prettier忽略规则
在.prettierignore 里添加忽略 eslint.config.mjs
,避免自动引入文件每次都要格式化代码
.prettierignore
node_modules
dist
public
*.min.js
auto-imports.d.ts
测试
通过上述步骤配置后,原先在未手动导入情况下报错的页面,现在可以正常使用 ref
, reactive
等 API,而无需显式导入。
以下是最终的效果:
整合按需自动导入后,你将不再需要在每个页面显式导入 Vue 或 UniApp 的组合式 API,大幅度减少了重复的代码,提升了开发体验。
环境变量
👉 Vue3 的环境变量是通过
.env
文件动态管理不同环境(如开发、测试、生产)的配置参数(如接口地址、端口等),以VITE_
为前缀声明,并通过import.meta.env
在代码中访问,实现不同环境下的灵活切换
下面的整合过程参考 Vite 环境变量配置官方文档
配置环境变量
项目根目录新建 .env.development
、.env.production
开发环境变量配置:.env.development
# 变量必须以 VITE_ 为前缀才能暴露给外部读取 # 项目运行的端口号 VITE_APP_PORT = 5173 # API 基础路径,开发环境下的请求前缀 VITE_APP_BASE_API = '/dev-api' # API 服务器的 URL VITE_APP_API_URL = https://api.moxun.api
生产环境变量配置:.env.production
# API 基础路径,生产环境下的请求前缀 VITE_APP_BASE_API = '/prod-api' # API 服务器的 URL VITE_APP_API_URL = https://api.moxun.api
智能提示
👉 在项目里提供提示
首先,在 src/types/env.d.ts
文件中添加环境变量的类型声明:
// src/types/env.d.ts
interface ImportMetaEnv {
/**
* 应用端口
*/
VITE_APP_PORT: number;
/**
* API 基础路径
*/
VITE_APP_BASE_API: string;
/**
* API 服务器的 URL
*/
VITE_APP_API_URL: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}
确保 TypeScript 编译器使用的模块系统支持 import.meta
。在 tsconfig.json
文件中,你可以指定 es2020
、es2022
或 esnext
等模块系统。例如:
// tsconfig.json
{
"compilerOptions": {
"module": "esnext", // 支持 import.meta
// ...
}
}
在任意页面中测试 import.meta
是否能够智能提示环境变量:
HTTP请求封装
👉 HTTP 请求封装通过统一管理接口配置、自动携带 Token、集中处理错误与缓存优化,减少重复代码,提升开发效率和代码维护性,并实现跨平台兼容性(如 H5 端适配)
通过一个登录案例演示如何在Uniapp中整合HTTP请求。这里未使用axios和alova请求库的原因在于,Uniapp自身提供了跨平台的uni.request方法,该方法在不同平台(如小程序、App和H5)下表现一致,且无需额外安装第三方库,从而减少了项目的依赖复杂性和体积。
封装请求工具
在 global.d.ts
中定义全局响应数据类型 ResponseData
:
// src/types/global.d.ts
declare global {
/**
* 响应数据结构
*/
interface ResponseData<T = any> {
code: string; // 业务状态码
data: T; // 返回数据
msg: string; // 消息
}
}
export {};
在 src/utils/request.ts
下创建一个 HTTP 请求工具,用于与 API 服务器进行通信:
// src/utils/request.ts
export default function request<T>(options: UniApp.RequestOptions): Promise<T> {
const token = uni.getStorageSync("token"); // 从本地缓存获取 token
return new Promise((resolve, reject) => {
uni.request({
...options,
// VITE_APP_API_URL 是在 Vite 项目的 .env.development 文件中配置的环境变量,表示 API 的路径
"url": `${import.meta.env.VITE_APP_API_URL}${options.url}`,
"header": {
...options.header,
"Authorization": token,
},
"success": (response) => {
const resData = response.data as ResponseData<T>;
// 业务状态码 00000 表示成功
if (resData.code === "00000") {
resolve(resData.data);
} else {
uni.showToast({
"title": resData.msg || "业务处理失败",
"icon": "none",
"duration": 2000,
});
reject({
"message": resData.msg || "业务处理失败",
"code": resData.code,
});
}
},
"fail": (error) => {
uni.showToast({
"title": "网络请求失败",
"icon": "none",
"duration": 2000,
});
reject({
"message": "网络请求失败",
error,
});
},
});
});
}
注意事项
当首次使用该请求工具类时,可能会出现 'uni' is not defined
的 ESLint 错误,如下图所示:
为解决此问题,需要在 ESLint 配置文件中定义 uni
为全局变量:
// eslint.config.mjs
export default [
{
// 语言选项配置,定义全局变量
languageOptions: {
globals: {
// ...
...{
uni: "readonly", // uni-app 全局对象
},
},
},
},
];
登录接口定义
请求URL: https://api.moxun.cn/api/v1/auth/login
请求参数:
表格 还在加载中,请等待加载完成后再尝试复制
返回响应:
{
"code": "200",
"data": {
"accessToken": "RyJ0eXDiOiJKV1WiLCJhbGcrOiJIUzI1NiJ9.eKJzdSIxxx.xxxxxxx",
"tokenType": "Bearer"
},
"msg": "ok"
}
根据上述登录接口信息,创建 AuthAPI
类用于处理登录请求:
import request from "@/utils/request";
const AuthAPI = {
/**
* 登录接口
*
* @param username 用户名
* @param password 密码
* @returns 返回 token
*/
login(username: string, password: string): Promise<LoginResult> {
return request<LoginResult>({
url: "/api/v1/auth/login",
method: "POST",
data: {
username,
password,
},
header: {
"Content-Type": "application/x-www-form-urlencoded",
},
});
},
/**
* 登出接口
*/
logout(): Promise<void> {
return request({
url: "/api/v1/auth/logout",
method: "DELETE",
});
},
};
export default AuthAPI;
/** 登录响应 */
export interface LoginResult {
/** 访问token */
accessToken?: string;
/** token 类型 */
tokenType?: string;
}
登录页面
新建 src/pages/login/index.vue
文件,编写登录页面及逻辑:
<template>
<view class="flex-col">
<input v-model="username" placeholder="请输入用户名" />
<input v-model="password" placeholder="请输入密码" type="password" />
<button @click="handleLogin">登录</button>
</view>
</template>
<script lang="ts" setup>
import AuthAPI, { LoginResult } from "@/api/auth";
const username = ref("");
const password = ref("");
const handleLogin = async () => {
try {
const response: LoginResult = await AuthAPI.login(username.value, password.value);
if (response.accessToken) {
uni.setStorageSync("token", response.accessToken);
uni.showToast({ "title": "登录成功", "icon": "success" });
} else {
uni.showToast({ "title": "登录失败", "icon": "none" });
}
} catch (err) {
uni.showToast({ "title": "登录失败", "icon": "none" });
}
};
</script>
<style scoped>
</style>
在 pages.json
文件中,声明登录页面的路由:
// src/pages.json
{
"pages": [
{
"path": "pages/login/index",
"style": {
"navigationBarTitleText": "登录"
}
}
]
}
登录测试
访问登录页面:http://localhost:5173/#/pages/login/index,输入用户名和密码 (admin
/123456
) 测试登录接口,登录成功后可以看到返回的访问令牌。
Pinia 状态管理
👉 Pinia 是 Vue 的状态管理库,专为跨组件或页面共享状态设计。
- Pinia 官方文档:
https://pinia.vuejs.org/zh/getting-started.html
安装依赖
首先,安装 pinia
依赖:
pnpm add pinia
全局注册
在项目的 src
目录下创建 store
文件夹,并新建 index.ts
文件,初始化并注册 Pinia 实例。
// src/store/index.ts
import type { App } from "vue";
import { createPinia } from "pinia";
const store = createPinia();
// 注册 Pinia
export function setupStore(app: App<Element>) {
app.use(store); // 全局注册 Pinia
}
接着,将 store
在项目入口文件 main.ts
中引入,并将其作为全局插件传递给应用:
// src/main.ts
import { createSSRApp } from "vue";
import App from "./App.vue";
import { setupStore } from "@/store";
export function createApp() {
const app = createSSRApp(App);
// 全局注册 store
setupStore(app);
return {
app,
};
}
接下来,我们通过 Pinia 管理登录状态和用户信息,并在多个页面共享状态。
用户信息接口
编写一个 API 来获取当前登录用户的信息:
import request from "@/utils/request";
const USER_BASE_URL = "/api/v1/users";
const UserAPI = {
/**
* 获取当前登录用户信息
*
* @returns 登录用户昵称、头像信息,包括角色和权限
*/
getUserInfo(): Promise<UserInfo> {
return request<UserInfo>({
url: `${USER_BASE_URL}/me`,
method: "GET",
});
},
};
export default UserAPI;
/** 登录用户信息 */
export interface UserInfo {
/** 用户ID */
userId?: number;
/** 用户名 */
username?: string;
/** 昵称 */
nickname?: string;
/** 头像URL */
avatar?: string;
/** 角色 */
roles: string[];
/** 权限 */
perms: string[];
}
用户状态管理
通过 Pinia 定义 user
模块,管理登录状态、用户信息等。
// src/store/module/user.ts
import { defineStore } from "pinia";
import AuthAPI from "@/api/auth";
import UserAPI, { UserInfo } from "@/api/user";
export const useUserStore = defineStore("user", () => {
// 确保 token 是响应式的
const token = ref<string>(uni.getStorageSync("token") || "");
const userInfo = ref<UserInfo | null>(null);
// 登录
const login = async (username: string, password: string) => {
const { tokenType, accessToken } = await AuthAPI.login(username, password);
token.value = `${tokenType} ${accessToken}`; // Bearer token
uni.setStorageSync("token", token.value);
};
// 获取用户信息
const getUserInfo = async () => {
const info = await UserAPI.getUserInfo();
userInfo.value = info;
};
// 登出
const logout = async () => {
await AuthAPI.logout();
userInfo.value = null;
token.value = ""; // 清空 token
uni.removeStorageSync("token"); // 从本地缓存移除 token
};
return {
token,
userInfo,
login,
logout,
getUserInfo,
};
});
个人中心页面
个人中心页面展示用户的头像和昵称,未登录时引导用户去登录。
<template>
<view class="flex-center flex-col">
<text class="text-blue font-bold text-lg">我的</text>
<!-- 判断是否已登录 -->
<template v-if="isLoggedIn">
<image :src="userInfo?.avatar" class="w100 h100 mb-5 rounded-full" />
<text class="text-lg font-bold">{{ userInfo?.nickname }}</text>
<button @click="handleLogout" class="mt-5">退出登录</button>
</template>
<!-- 未登录时显示去登录按钮 -->
<template v-else>
<text>您还未登录,请先登录</text>
<button @click="goToLoginPage" class="mt-5">去登录</button>
</template>
</view>
</template>
<script lang="ts" setup>
import { useUserStore } from "@/store/modules/user";
// 使用 pinia
const userStore = useUserStore();
const isLoggedIn = computed(() => userStore.token);
const userInfo = computed(() => userStore.userInfo);
// 跳转到登录页面
const goToLoginPage = () => {
uni.navigateTo({ url: "/pages/login/index" });
};
// 退出登录处理
const handleLogout = async () => {
await userStore.logout();
uni.showToast({ title: "已退出登录", icon: "success" });
};
</script>
登录页通过 Pinia
实现用户信息的全局状态管理,并在登录成功后跳转到个人中心页面。
源码版本
https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2FPinia/
反向代理
👉 反向代理是通过配置开发服务器(如vue.config.js
中的devServer.proxy
),将前端请求转发至目标后端服务器,解决跨域问题并简化API调用,例如将/api
路径请求代理到真实后端地址,实现开发环境下的无缝通信
在开发中,若服务端没有启用 CORS(跨域资源共享),浏览器会基于安全策略拦截跨域请求,导致无法访问接口。为了绕过这个问题,我们可以通过 Vite 的反向代理功能,将开发阶段的请求代理到真实的 API 服务器上,伪装成同源请求。
环境变量配置
之前我们已经配置了环境变量,以下是 .env.development
中的相关配置:
# 变量必须以 VITE_ 为前缀才能暴露给外部读取
# 项目运行的端口号
VITE_APP_PORT = 5173
# API 基础路径,开发环境下的请求前缀
VITE_APP_BASE_API = '/dev-api'
# API 服务器的 URL
VITE_APP_API_URL = https://api.moxun.cn
请求工具的调整
为了让请求走代理,我们需要在请求工具中将 VITE_APP_API_URL
替换为 VITE_APP_BASE_API
。这样,所有对 API
的请求都会通过代理标识 /dev-api
进行转发。
export default function request<T>(options: UniApp.RequestOptions): Promise<T> {
return new Promise((resolve, reject) => {
uni.request({
...options,
// 原请求方式: 使用真实 API URL
// url: `${import.meta.env.VITE_APP_API_URL}${options.url}`, // 示例: https://api.moxun.cn/login
// VITE_APP_BASE_API 是在 Vite 项目的 .env.development 文件中配置的环境变量,使用代理标识,实际转发到真实 API
url: `${import.meta.env.VITE_APP_BASE_API}${options.url}`, // 示例: http://localhost:5173/dev-api/login
});
});
}
Vite 反向代理配置
接下来,在 vite.config.ts
中添加反向代理配置,将 /dev-api
的请求代理到 VITE_APP_API_URL
,通过 http-proxy
实现请求的转发。
// vite.config.ts
import { defineConfig, UserConfig, ConfigEnv, loadEnv } from "vite";
export default defineConfig(async ({ mode }: ConfigEnv): Promise<UserConfig> => {
const env = loadEnv(mode, process.cwd());
return {
server: {
host: "0.0.0.0",
port: +env.VITE_APP_PORT,
open: true,
// 反向代理配置
proxy: {
[env.VITE_APP_BASE_API]: {
target: env.VITE_APP_API_URL, // 目标服务器
changeOrigin: true, // 支持跨域
rewrite: (path) => path.replace(new RegExp("^" + env.VITE_APP_BASE_API), ""), // 去掉前缀
},
},
},
plugins: [
// 插件配置...
],
};
});
测试与验证
在配置好反向代理后,浏览器发出的请求将被 Vite 的代理服务器拦截并转发至真实的 API 地址。例如,浏览器请求 http://localhost:5173/dev-api/api/v1/auth/login
时,Vite 会将该请求代理到 https://api.moxun.cn/api/v1/auth/login。
浏览器认为请求的 URL 与应用的主机地址一致,因此不会阻止该请求,即便真实请求已通过代理转发到外部服务器。
需要注意,反向代理的目标是伪装请求来源,虽然它绕过了浏览器的同源策略,但有时也会让开发者误以为请求地址错误。实际上,这是由于代理转发过程造成的表面请求地址与真实请求地址的差异。
源码地址
https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2Fdev1.0/
五、UI 框架集成
uView-plus(适配Vue3的版本)
官网地址:https://uiadmin.net/uview-plus/components/intro.html
👉 uview-plus是uni-app生态专用的UI框架,uni-app 是一个使用 Vue.js 开发所有前端应用的框架,开发者编写一套代码, 可发布到iOS、Android、H5、以及各种小程序(微信/支付宝/百度/头条/QQ/钉钉)等多个平台(引言自uni-app网)。但目前除微信小程序,其它小程序平台的兼容可能存在一些问题,后续会针对这方面持续优化。
安装uView-plus核心库
pnpm add uview-plus # 或npm/yarn
配置main.ts
在src/main.ts
中引入并挂载uView:
import { createSSRApp } from 'vue'
import App from './App.vue'
import uViewPlus from 'uview-plus'
export function createApp() {
const app = createSSRApp(App)
app.use(uViewPlus)
return { app }
}
类型声明配置(TypeScript项目)
修改src/env.d.ts
,添加类型声明:
/// <reference types="vite/client" />
declare module 'uview-plus'
样式文件引入
全局SCSS变量(uni.scss)
在项目根目录的uni.scss
中添加:
@import 'uview-plus/theme.scss';
基础样式(App.vue)
在App.vue
的<style>
中引入:
<style lang="scss">
@import "uview-plus/index.scss";
</style>
自动导入组件配置
配置easycom规则
在pages.json
中添加:
{
"easycom": {
"autoscan": true,
"custom": {
"^u-(.*)": "uview-plus/components/u-$1/u-$1.vue",
"^up-(.*)": "uview-plus/components/u-$1/u-$1.vue"
}
}
}
验证安装
测试组件
在页面中使用uView组件,例如:
<template>
<view>
<u-button type="primary">测试按钮</u-button>
</view>
</template>
重启项目
运行pnpm dev:mp-weixin
(或其他平台命令),查看组件是否正常渲染。
Sass报警@import
在sass1.8.0以上版本报错Deprecation Warning: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. 因为新版本Sass的@use语法较为激进,如果升级为@use将会是破坏式更新,所以推荐将sass固定在以下版本结局报警。
"sass": "1.63.2",
"sass-loader": "10.4.1",
源码
整合uview-plus
代码版本: https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2Fdev2.0-uviewPlus/
wot-design-uni
👉 wot-design-uni
是基于 Vue 3
和 TypeScript
构建的高质量组件库。组件库遵循 Wot Design
的设计规范,提供 70 多个组件,支持暗黑模式、国际化和自定义主题,旨在为开发者提供一致的 UI 交互,同时提高开发效率。
说明: 本文档整合步骤基于
wot-design-uni
官方文档编写,建议开发者参考 官方文档 进行安装和配置,以确保组件库的正确使用。
安装依赖
使用 pnpm
安装组件库的依赖:
pnpm add wot-design-uni
配置自动引入组件
在 pages.json
文件中配置 easycom
自动引入:
// pages.json
{
"easycom": {
"autoscan": true,
"custom": {
"^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue"
}
},
"pages": [
// 这里是项目已有的内容
]
}
关于 easycom
* :* easycom
是 uni-app
提供的自动化引入功能,更多细节请参考 easycom 官方文档。
Volar 支持
为了让 Volar
正确识别和提示全局组件,你需要在项目的 tsconfig.json
文件中配置全局组件类型支持:
// tsconfig.json
{
"compilerOptions": {
"types": ["wot-design-uni/global"]
}
}
这将确保你在 TypeScript
项目中编写代码时,Volar 能提供完整的类型支持和代码提示。
测试组件
安装和配置完成后,你可以开始使用 wot-design-uni
的组件。在页面中,直接写组件标签即可,无需手动导入和注册:
<template>
<view>
<wd-button size="small">主要按钮</wd-button>
<wd-button type="success" size="small">成功按钮</wd-button>
<wd-button type="info" size="small">信息按钮</wd-button>
<wd-button type="warning" size="small">警告按钮</wd-button>
<wd-button type="error" size="small">危险按钮</wd-button>
</view>
</template>
你将看到如下按钮效果:
Sass报警@import
在sass1.8.0以上版本报错Deprecation Warning: Sass @import rules are deprecated and will be removed in Dart Sass 3.0.0. 因为新版本Sass的@use语法较为激进,如果升级为@use将会是破坏式更新,所以推荐将sass固定在以下版本解决报警。
"sass": "1.63.2",
"sass-loader": "10.4.1",
源码
整合wot-design-uni
代码版本: https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2Fdev2.0-Wot/
六、项目部署
H5 部署
👉 执行 pnpm run build:h5
命令来完成项目的打包:
pnpm run build:h5
打包后生成的静态文件位于 dist/build/h5
目录下。将该目录下的文件复制到服务器的 /usr/share/nginx/html/``uniapp-vue3-template
目录。
接下来,配置 nginx:
# nginx.conf
server {
listen 80;
server_name localhost;
location / {
root /usr/share/nginx/html/uniapp-vue3-template;
index index.html index.htm;
}
# 反向代理配置
location /prod-api/ {
# 将 api.moxun.cn替换为后端 API 地址,注意保留后面的斜杠 /
proxy_pass http://api.moxun.cn/;
}
}
这样配置完成后,就可以通过 nginx
服务器来访问你的项目了。
小程序发布
👉 微信小程序是微信生态内无需下载安装的轻量级应用,支持即用即走、跨平台运行(iOS/Android),提供原生体验及微信核心功能(支付、分享等),降低开发成本并提升用户触达效率。
下载工具
下载 HBuilder X 编辑器
下载 微信开发者工具
获取小程序 AppID
访问 微信公众平台申请小程序,获取 AppID
。如果已申请,可在 首页
→ 小程序信息
→ 查看详情
查看 AppID
配置项目
使用 HBuilder X 打开项目,修改 manifest.json
文件中的小程序配置,并填写获取的 AppID。
设置微信开发者工具
使用微信扫码登录微信开发者工具,开启服务端口:点击工具栏设置
→安全设置
→安全
→服务端口
,选择打开。
运行项目
在 HBuilder X 中,点击 运行
→运行到小程序模拟器
→微信开发者工具
。
项目编译完成后,微信开发者工具会自动启动并呈现页面。
上传发布
在微信开发者工具中,点击 上传
将应用发布到小程序平台。
查看效果
最后,使用手机打开小程序查看效果.
结语
通过本文的系统讲解,我们完整呈现了如何从零构建一个基于 Vue3 + TypeScript 的 UniApp 跨端开发脚手架。整个流程涵盖了:
基础环境搭建 - 从 Node.js 环境配置到 Vue CLI 安装
项目初始化 - 创建支持 Vite 和 TypeScript 的 uni-app 项目模板
代码规范体系 - 集成 ESLint + Prettier + Stylelint 的完整前端规范解决方案
工程化配置 - 通过 Husky + lint-staged + Commitizen 实现 Git 提交规范化
核心功能集成 - 包括:
- UnoCSS 原子化样式方案
- Pinia 状态管理
- 自动按需导入
- HTTP 请求封装
- 环境变量管理
组件库整合 - 接入 wot-design-uni 组件库
多端部署 - 详细说明 H5 和小程序的发布流程
这个名为 uniapp-vue3-template 的开源项目已完整实现上述所有功能,其特色在于:
✅ 开箱即用的工程化配置
✅ 严格的代码质量管控
✅ 高效的开发体验优化
✅ 完善的类型系统支持
✅ 灵活的多端适配能力
项目源码已完全开源,地址: https://gitee.com/moxunjinmu/uniapp-vue3-template
uview-plus
代码版本: https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2Fdev2.0-uviewPlus/
wot-design-uni
代码版本: https://gitee.com/moxunjinmu/uniapp-vue3-template/tree/dev%2Fdev2.0-Wot/
Gitee开源地址: https://gitee.com/moxunjinmu/uniapp-vue3-template
Github开源地址: https://github.com/moxunjinmu/uniapp-vue3-template
项目持续欢迎开发者参与项共建,您可以通过以下方式贡献:
- 提交 Issue 反馈问题
- 发起 Pull Request 贡献代码
- 分享使用案例和经验
- 提出改进建议
期待与更多开发者一起完善这个项目,为 uni-app 生态提供更优质的开发解决方案。如果您有任何疑问或合作意向,欢迎联系作者(+V:moxunjinmu)。
最后,感谢所有参与项目的贡献者,也感谢您的阅读和实践!希望这个模板能为您的跨端开发之旅提供切实帮助。