当前位置: 首页 > news >正文

从0到1构建 UniApp + Vue3 + TypeScript 移动端跨平台开源脚手架

在这里插入图片描述

🚀 作者主页: 有来技术
🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🍃 vue-uniapp-template
🌺 仓库主页: GitCode💫 Gitee 💫 Github
💖 欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请纠正!

开局一张图,先看一下初期登录的效果图,内容和UI正在升级中…
在这里插入图片描述

目录

    • 前言
    • 环境准备
      • 安装 Node
      • 安装 VSCode
      • 安装 vue-cli
    • 创建项目
      • 初始化项目
      • 配置编译器
      • 启动项目
    • 代码规范配置
      • 集成 ESLint
        • 安装插件
        • 配置 ESLint
        • 添加 ESLint 脚本
        • 测试效果
        • 推荐配置
      • 集成 Prettier
        • 安装插件
        • 安装依赖
        • 配置 Prettier
        • 配置忽略文件
        • 添加格式化脚本
        • 保存自动格式化
        • 测试
      • 集成 Stylelint
        • 安装插件
        • 安装依赖
        • 配置 Stylelint
        • 配置忽略文件
        • 添加 Stylelint 脚本
        • 保存自动修复
        • 测试
    • Git提交规范配置
      • 集成 Husky
        • 安装依赖
        • 初始化
        • 测试
      • 集成 lint-staged
        • 安装依赖
        • 配置 lint-staged
        • 添加 Husky 钩子
        • 测试
      • 集成 Commitlint
        • 安装依赖
        • 配置 Commitlint
        • 添加 Husky 钩子
        • 测试
      • 集成 Commitizen 和 cz-git
        • 安装依赖
        • 配置 cz-git
        • 添加 cz-git 脚本
        • 测试
    • 整合 Sass
    • 整合 UnoCSS
      • 安装插件
      • 安装依赖
      • 配置 UnoCSS
      • 测试
    • 添加 TabBar
      • 添加页面
      • 添加图标
      • 配置 TabBar
      • 测试
    • 按需自动导入
      • 安装依赖
      • 配置自动导入
      • 配置 ESLint 规则
      • 测试
    • 环境变量
      • 配置环境变量
      • 智能提示
    • 整合 HTTP 请求
      • 封装请求工具
      • 登录接口定义
      • 登录页面
      • 登录测试
      • 整合源码
    • 整合 Pinia
      • 安装依赖
      • 全局注册
      • 用户信息接口
      • 用户状态管理
      • 个人中心页面
      • 测试效果
      • 整合源码
    • 反向代理
      • 环境变量配置
      • 请求工具的调整
      • Vite 反向代理配置
      • 测试与验证
      • 整合源码
    • 整合 wot-design-uni
      • 安装依赖
      • 配置自动引入组件
      • Volar 支持
      • 测试组件
      • 整合源码
    • 项目部署
      • H5 部署
      • 小程序发布
        • 下载工具
        • 获取小程序 AppID
        • 配置项目
        • 设置微信开发者工具
        • 运行项目
        • 上传发布
        • 查看效果
    • 结语
    • 附:项目源码

前言

本文旨在从零开始,通过 vue-cli 构建一个基于 Vue3 和 TypeScript 的 UniApp 跨移动端开源脚手架模板。通过详实的步骤讲解,从环境配置到项目部署,全面涵盖开发中的各个重要环节,致力于打造高效的开发工具,提升项目质量和开发效率。

环境准备

vue-uniapp-template 是一个通过 vue-cli 构建的跨移动端脚手架模板,结合了 uniappvue3 typescript 主流技术栈。在开始之前,需要准备以下环境。如果环境准备OK,请忽略本节。

安装 Node

Node.js 是运行 JavaScript 代码的环境,也是 npm 包管理器的依赖。

打开 Node.js 官方下载页面,根据你的操作系统选择合适的版本进行下载,推荐安装 LTS 版本,这是长期支持版本,适合开发环境,比如这里选择 v20.18.0(LTS) 版本。

下载之后,双击安装包根据提示安装,通过以下命令检查是否成功安装:

node -v

安装 VSCode

VSCode 是一款非常流行的代码编辑器,特别适合前端开发。

访问 Visual Studio Code 官方网站 ,根据你的操作系统下载相应版本的 VSCode ,下载完成后,双击安装程序并按照提示完成安装。

安装 vue-cli

Vue CLI 是 Vue.js 的命令行工具,能够快速创建、开发、构建 Vue.js 项目。

打开终端或命令提示符, 使用 npm 全局安装 Vue CLI

npm install -g @vue/cli

安装完成后,检查 Vue CLI 是否安装成功:

vue --version

在这里插入图片描述

创建项目

初始化项目

按照 uni-app 官方文档 的步骤,通过 vue-cli 创建 uni-app + vue + typescript 脚手架:

npx degit dcloudio/uni-preset-vue#vite-ts vue-uniapp-template

在这里插入图片描述

如果使用命令创建失败,可以通过 Gitee 下载 ZIP 包:vite-ts 分支。

配置编译器

默认生成的 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"]},"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],"exclude": ["node_modules", "dist"]
}
  • "module": "esnext": 指定模块系统为 ESNext,即最新的 ECMAScript 模块系统,支持 import.meta 和其他最新的特性。
  • "moduleResolution": "node": 模块解析策略,通常设置为 Node 以支持 Node.js 风格的模块解析。
  • "target": "esnext": 将目标 JavaScript 版本设置为 ESNext,编译输出现代浏览器能够支持的最新特性代码。
  • "allowJs": true: 允许 TypeScript 编译器处理 .js 文件,混合使用 TypeScript 和 JavaScript 文件。
  • "skipLibCheck": true: 跳过库文件的类型检查,提升编译速度。
  • "strict": true : 启用所有严格类型检查选项。

启动项目

创建完成后,使用 VSCode 打开项目并启动:

# 安装依赖
pnpm install
# 启动项目
pnpm run dev:h5

在这里插入图片描述

项目启动后,访问 http://localhost:5173 预览效果:

在这里插入图片描述

代码规范配置

为了保证项目代码的规范性和一致性,可以为项目配置 ESLintStylelintPrettier 以及 Husky,从而确保代码质量和开发流程的一致性。

集成 ESLint

ESLint 是一款 JavaScript 和 TypeScript 的代码规范工具,能够帮助开发团队保持代码风格一致并减少常见错误。

ESLint 中文网:https://eslint.nodejs.cn/

安装插件

VSCode 插件市场搜索 ESLint 插件并安装

在这里插入图片描述

配置 ESLint

通过以下命令快速生成 ESLint 配置文件:

npx eslint --init

在这里插入图片描述

执行该命令后,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 脚本

为了方便使用 ESLint,可以在 package.json 中添加 lint 脚本命令:

{"scripts": {"lint:eslint": "eslint --fix ./src"}
}

此脚本会自动修复符合 ESLint 规则的代码问题,并输出检查结果。

测试效果

App.vue 文件中声明一个未使用的变量,并运行 pnpm run lint:eslint,可以看到 ESLint 提示该变量未使用。如下图所示:

在这里插入图片描述

推荐配置

安装 Vue 文件解析器 vue-eslint-parser

pnpm add -D vue-eslint-parser

针对不同文件配置插件和解析器:

// 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 是一个代码格式化工具,能够和 ESLint 配合使用,确保代码风格统一。

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.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 的 FilePreferencesSettings,然后选择 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
依赖说明备注
postcssCSS 解析工具,允许使用现代 CSS 语法并将其转换为兼容的旧语法-
postcss-html解析 HTML (类似 HTML) 的 PostCSS 语法参见 postcss-html 文档
postcss-scssPostCSS 的 SCSS 解析器参见 postcss-scss 文档,支持 CSS 行类注释
stylelintstylelint 核心库参见 stylelint
stylelint-config-recommended提供了基础的 Stylelint 配置,适用于大多数项目,允许自定义规则集与 stylelint-config-standard 相比,此配置提供了更多的灵活性
stylelint-config-recommended-scss扩展基础配置,为 SCSS 特定规则提供支持参见 stylelint-config-recommended-scss 文档
stylelint-config-recommended-vue扩展基础配置,为 Vue 文件中的样式提供支持参见 stylelint-config-recommended-vue 文档
stylelint-config-recess-order提供优化样式顺序的配置参见 CSS 书写顺序规范
stylelint-config-html为 HTML (类似 HTML) 文件提供共享配置参见 stylelint-config-html 文档
stylelint-prettier集成 stylelint 和 prettier,确保样式同时满足两个工具的规范-

其中选择 stylelint-config-recommended 替代 stylelint-config-standard 的原因在于它不仅提供了灵活性,还更加轻量。stylelint-config-recommended 默认包含的规则较少,避免了 stylelint-config-standard 中可能不需要的规则,这样可以减少配置的复杂度,提高项目的启动速度,同时让开发者能够集中关注对项目真正重要的风格指南。轻量配置有助于简化工作流程,特别是在大型或复杂的项目中。

配置 Stylelint

根目录新建 .stylelintrc.cjs 文件,配置如下:

{"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-commitcommit-msg 钩子,实现代码提交的自动化检查和规范化。

  • pre-commit: 使用 Husky + Lint-staged,在提交前进行代码规范检测和格式化。确保项目已配置 ESLint、Prettier 和 Stylelint。
  • commit-msg: 结合 Husky、Commitlint、Commitizen 和 cz-git,生成规范化且自定义的 Git commit 信息。

在这里插入图片描述

集成 Husky

Husky 是 Git 钩子工具,可以设置在 git 各个阶段(pre-commitcommit-msg 等)触发。

Husky官网:https://typicode.github.io

在这里插入图片描述

安装依赖
pnpm add -D husky
初始化

init 命令简化了项目中的 husky 设置。它会在 .husky/ 中创建 pre-commit 脚本,并更新 package.json 中的 prepare 脚本。

pnpm exec husky init
测试

在这里插入图片描述

通过 pre-commit 钩子,可以自动运行各种代码检查工具,在提交代码前强制执行代码质量和样式检查。常见的工具包括:

  • eslint:用于检查和修复 JavaScript/TypeScript 代码中的问题。
  • stylelint:用于检测和修复 CSS/SCSS 样式问题。

接下来,集成 lint-stagedcommitlint 来进一步完善开发体验。

集成 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.jsonscripts 部分中,添加用于运行 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 的提交规范,提交信息由以下部分组成:

  1. 类型:表示本次提交的类型,例如 feat (新功能)、fix (修复 bug)、docs (文档更新)。
  2. 作用域(可选):说明本次提交影响的模块,例如 authui
  3. 简短描述:简洁明了的提交描述,限定在 50 字符以内。

当你尝试提交不符合规范的提交信息时,提交会被阻止,并显示相关错误提示。如下图所示:

在这里插入图片描述

集成 Commitizen 和 cz-git

  • commitizen: 是一个帮助开发者以标准化格式生成提交信息的工具。–Commitizen 官方文档

  • cz-git: cz-gitCommitizen 的适配器之一,它基于 Commitizen,提供了更多自定义功能和增强的交互体验。–cz-git 官方文档

安装依赖
pnpm add -D 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-ignoretypes: [{ 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"}
测试

执行 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

    vite.config.ts 中添加如下配置,整合 UnoCSS 到 UniApp 项目:

    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(),// 配置 UnoCSSUnoCss(),],}
    })
    
  • 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-weapppresetWeapp(),// attributify autocompletepresetWeappAttributify(),],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/transformerAttributifytransformerAttributify(),// https://github.com/MellowCo/unocss-preset-weapp/tree/main/src/transformer/transformerClasstransformerClass(),],
    };

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/work/index.vue):

    <template><view class="flex-center flex-col"><view><text class="text-cyan font-bold text-lg">工作台</text></view></view>
    </template>
    
  • 我的页面src/pages/my/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": [{"path": "pages/index/index","style": {"navigationBarTitleText": "首页"}},{"path": "pages/work/index","style": {"navigationBarTitleText": "工作台"}},{"path": "pages/mine/index","style": {"navigationBarTitleText": "我的"}}],"tabBar": {"color": "#474747","selectedColor": "#3B8DFF","backgroundColor": "#F8F8F8","list": [{"pagePath": "pages/index/index","text": "首页","iconPath": "static/tabbar/home.png","selectedIconPath": "static/tabbar/home-active.png"},{"pagePath": "pages/work/index","text": "工作台","iconPath": "static/tabbar/work.png","selectedIconPath": "static/tabbar/work-active.png"},{"pagePath": "pages/mine/index","text": "我的","iconPath": "static/tabbar/mine.png","selectedIconPath": "static/tabbar/mine-active.png"}]}
}

测试

在这里插入图片描述

按需自动导入

在传统的 Vue 开发中,我们通常需要在每个页面手动导入 Vue 组合式 API(如 ref, reactive, onMounted 等)。随着项目的增大,手动导入会增加代码的冗余度,降低开发体验。

通过对比,来看一下手动导入与按需自动导入的区别:

手动导入按需自动导入
在这里插入图片描述在这里插入图片描述

手动导入: 每个页面都需要显式地引入 ref, reactive, onMounted 等组合式 API。
按需自动导入: 配置了自动导入插件后,这些 API 无需显式导入即可直接使用,减少了重复代码,提高了开发效率。

由于当前还未整合按需自动导入插件,所以右图的代码仍然报错,提示未找到 refreactive 的定义。这展示了按需自动导入的重要性:一旦整合插件,这类错误将被消除,代码更加简洁易维护。

安装依赖

首先使用以下命令安装 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 AutoImport from "unplugin-auto-import/vite";export default defineConfig(async () => {return {plugins: [uni(), // 这里是你的 uni-app 插件AutoImport({imports: ["vue", "uni-app"], // 自动导入 Vue 和 UniApp 的 APIdts: "src/types/auto-imports.d.ts", // 自动生成类型声明文件eslintrc: {enabled: true, // 生成 ESLint 配置文件filepath: './.eslintrc-auto-import.json', // ESLint 配置文件路径},}),],};
});

配置 ESLint 规则

为了让 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 这样的错误,从而使项目的开发更加顺畅。

测试

通过上述步骤配置后,原先在未手动导入情况下报错的页面,现在可以正常使用 ref, reactive 等 API,而无需显式导入。

以下是最终的效果:

在这里插入图片描述

整合按需自动导入后,你将不再需要在每个页面显式导入 Vue 或 UniApp 的组合式 API,大幅度减少了重复的代码,提升了开发体验。

环境变量

Vite 环境变量主要是为了区分开发、测试、生产等环境的变量

下面的整合过程参考 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.youlai.tech
    
  • 生产环境变量配置:.env.production

    # API 基础路径,生产环境下的请求前缀
    VITE_APP_BASE_API = '/prod-api'# API 服务器的 URL
    VITE_APP_API_URL = https://api.youlai.tech
    

智能提示

首先,在 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 文件中,你可以指定 es2020es2022esnext 等模块系统。例如:

// tsconfig.json
{"compilerOptions": {"module": "esnext",  // 支持 import.meta// ...}
}

在任意页面中测试 import.meta 是否能够智能提示环境变量:

console.log(import.meta.env.VITE_APP_PORT);

在这里插入图片描述

整合 HTTP 请求

通过一个登录案例演示如何在Uniapp中整合HTTP请求。这里未使用axiosalova请求库的原因在于,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"); // 从本地缓存获取 tokenreturn 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.youlai.tech/api/v1/auth/login

请求参数:

参数名参数值
usernameadmin
password123456

返回响应:

{"code": "00000","data": {"accessToken": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIxxx.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 router = useRouter();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) 测试登录接口,登录成功后可以看到返回的访问令牌。

在这里插入图片描述

整合源码

整合HTTP请求代码版本:vue-uniapp-template#737f6a3。

整合 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);// 全局注册 storesetupStore(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 tokenuni.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 = ""; // 清空 tokenuni.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 实现用户信息的全局状态管理,并在登录成功后跳转到个人中心页面。

<template><view class="flex-col items-center"><input v-model="username" placeholder="请输入用户名" /><input v-model="password" placeholder="请输入密码" type="password" /><button class="mt-5" @click="handleLogin">登录</button></view>
</template><script lang="ts" setup>
import { useUserStore } from "@/store/modules/user";// 登录表单
const username = ref("admin");
const password = ref("123456");// 使用 pinia
const userStore = useUserStore();// 登录处理
const handleLogin = async () => {await userStore.login(username.value, password.value);if (!!userStore.token) {await userStore.getUserInfo(); // 登录成功后获取用户信息uni.showToast({ title: "登录成功", icon: "success" });uni.navigateBack(); // 登录成功后返回上一页} else {uni.showToast({ title: "登录失败", icon: "none" });}
};
</script><style scoped>
input {width: 80%;padding: 10px;margin-top: 16px;border: 1px solid #ccc;
}
</style>

测试效果

登录后,个人中心会显示用户的头像和昵称。通过 Pinia 实现了登录状态的共享和跨页面传递。

在这里插入图片描述

整合源码

整合Pinia代码版本:vue-uniapp-template#737f6a3。

反向代理

在开发中,若服务端没有启用 CORS(跨域资源共享),浏览器会基于安全策略拦截跨域请求,导致无法访问接口。为了绕过这个问题,我们可以通过 Vite 的反向代理功能,将开发阶段的请求代理到真实的 API 服务器上,伪装成同源请求。

本节将介绍如何配置 Vite 的反向代理来处理跨域请求。


环境变量配置

我们将通过环境变量来管理项目端口和 API 请求地址,以下是 .env.development 中的相关配置:

# .env.development# 项目运行的端口号
VITE_APP_PORT=5173# API 请求的基础路径(开发环境)
VITE_APP_BASE_API=/dev-api# 真实 API 服务器的 URL
VITE_APP_API_URL=https://api.youlai.tech

请求工具的调整

为了让请求走代理,我们需要在请求工具中将 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.youlai.tech/login// 修改后:使用代理标识,实际转发到真实 APIurl: `${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.youlai.tech/api/v1/auth/login

下图展示了这一过程,浏览器认为请求的 URL 与应用的主机地址一致,因此不会阻止该请求,即便真实请求已通过代理转发到外部服务器。

在这里插入图片描述

需要注意,反向代理的目标是伪装请求来源,虽然它绕过了浏览器的同源策略,但有时也会让开发者误以为请求地址错误。实际上,这是由于代理转发过程造成的表面请求地址与真实请求地址的差异。

整合源码

整合反向代理环境变量代码版本:vue-uniapp-template#272d643。

整合 wot-design-uni

wot-design-uni 是基于 Vue 3TypeScript 构建的高质量组件库。组件库遵循 Wot Design 的设计规范,提供 70 多个组件,支持暗黑模式、国际化和自定义主题,旨在为开发者提供一致的 UI 交互,同时提高开发效率。

说明: 本文档整合步骤基于 wot-design-uni 官方文档编写,建议开发者参考 官方文档 进行安装和配置,以确保组件库的正确使用。


安装依赖

根据官方文档,使用 pnpm 安装组件库的依赖:

pnpm add wot-design-uni

配置自动引入组件

在传统的 Vue 项目中,使用组件需要手动安装、引用、注册。而使用 easycom 可以简化这些操作。只要组件路径符合规范,就可以直接在页面中使用,无需手动导入和注册。

pages.json 文件中配置 easycom 自动引入:

// pages.json
{"easycom": {"autoscan": true,"custom": {"^wd-(.*)": "wot-design-uni/components/wd-$1/wd-$1.vue"}},"pages": [// 这里是项目已有的内容]
}

关于 easycom
easycomuni-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>

你将看到如下按钮效果:
在这里插入图片描述

整合源码

整合wot-design-uni 代码版本:vue-uniapp-template#a775721。

项目部署

H5 部署

执行 pnpm run build:h5 命令来完成项目的打包:

pnpm run build:h5

打包后生成的静态文件位于 dist/build/h5 目录下。将该目录下的文件复制到服务器的 /usr/share/nginx/html/vue-uniapp-template 目录。

接下来,配置 nginx:

# nginx.conf
server {listen 80;server_name localhost;location / {root /usr/share/nginx/html/vue-uniapp-template;index index.html index.htm;}# 反向代理配置location /prod-api/ {# 将 api.youlai.tech 替换为后端 API 地址,注意保留后面的斜杠 /proxy_pass http://api.youlai.tech/; }
}

这样配置完成后,就可以通过 nginx 服务器来访问你的项目了。

小程序发布

下载工具

下载 HBuilder X 编辑器

在这里插入图片描述

下载 微信开发者工具

在这里插入图片描述

获取小程序 AppID

访问 微信公众平台申请小程序,获取 AppID。如果已申请,可在 首页小程序信息查看详情 查看 AppID

在这里插入图片描述

在这里插入图片描述

配置项目

使用 HBuilder X 打开项目,修改 manifest.json 文件中的小程序配置,并填写获取的 AppID。

在这里插入图片描述

设置微信开发者工具

使用微信扫码登录微信开发者工具,开启服务端口:点击工具栏设置安全设置安全服务端口,选择打开。

在这里插入图片描述

运行项目

在 HBuilder X 中,点击 运行运行到小程序模拟器微信开发者工具

在这里插入图片描述

项目编译完成后,微信开发者工具会自动启动并呈现页面。

在这里插入图片描述

上传发布

在微信开发者工具中,点击 上传 将应用发布到小程序平台。

在这里插入图片描述

在这里插入图片描述

查看效果

最后,使用手机打开小程序查看效果:

在这里插入图片描述

结语

通过本文的详细讲解,相信你已经掌握了如何从零搭建一个高效的、基于 Vue3 和 TypeScript 的 UniApp 跨移动端解决方案脚手架模板——vue-uniapp-template。无论是代码规范、状态管理、样式配置,还是 Git 提交规范与项目部署,都能帮助你在实际项目中提高开发效率和代码质量。

希望本文能为你的项目开发提供全面的指导与支持,助你快速搭建出一个高效的跨移动端解决方案。Happy 1024 & Happy Coding!

附:项目源码

本篇文章涉及的源码已开源,项目地址:https://gitee.com/youlaiorg/vue-uniapp-template ,项目正在努力建设中,希望有兴趣参与开源的小伙伴们联系我(haoxianrui)。

相关文章:

从0到1构建 UniApp + Vue3 + TypeScript 移动端跨平台开源脚手架

&#x1f680; 作者主页&#xff1a; 有来技术 &#x1f525; 开源项目&#xff1a; youlai-mall &#x1f343; vue3-element-admin &#x1f343; youlai-boot &#x1f343; vue-uniapp-template &#x1f33a; 仓库主页&#xff1a; GitCode&#x1f4ab; Gitee &#x1f…...

论文笔记:LaDe: The First Comprehensive Last-mile Delivery Dataset from Industry

2023 KDD 1 intro 1.1 背景 随着城市化进程的加快和电子商务的发展&#xff0c;最后一公里配送已成为一个关键的研究领域 最后一公里配送&#xff0c;如图1所示&#xff0c;是指连接配送中心和客户的包裹运输过程&#xff0c;包括包裹的取件和配送除了对客户满意度至关重要外…...

无用的知识又增加了-静态二值贝叶斯滤波

静态二值贝叶斯滤波 静态二值贝叶斯滤波&#xff08;Static Binary Bayes Filter&#xff09;是一种用于处理二值状态&#xff08;例如&#xff0c;目标存在或不存在&#xff09;的简单贝叶斯滤波器。这种滤波器通常应用于目标检测、传感器融合等场景&#xff0c;其中状态空间…...

cesium相机(camera)控制

camera基础属性&#xff1a; Cesium 中的相机通过 viewer.camera 来获取和操作。 position:相机的位置,用 Cartesian3 坐标表示&#xff0c;表示的是相机在世界坐标系中的绝对位置。 viewer.camera.position Cesium.Cartesian3.fromDegrees(longitude, latitude, height);dir…...

Java 反射

一、基本概念 Java反射机制是Java语言的一种动态特性&#xff0c;允许程序在运行时检查和操作类、接口、字段和方法。反射机制使得Java程序可以在运行时获取关于类的详细信息&#xff0c;并且可以动态地调用类的方法、访问类的字段等。反射机制主要涉及以下几个核心类和接口&a…...

【目标检测01】真实框、预测框、锚框和交并比IoU

文章目录 1. 任务定义2. 基本概念2.1 边界框&#xff08;bounding box&#xff09;2.2 真实框、预测框和锚框2.3 交并比 (IoU)2.4 代码实现 1. 任务定义 目标检测的主要目的是让计算机可以自动识别图片或者视频帧中所有目标的类别&#xff0c;并在该目标周围绘制边界框&#x…...

青少年编程能力等级测评CPA C++五级试卷(2)

青少年编程能力等级测评CPA C++五级试卷(2) 一、单项选择题(共15题,每题3分,共45分) CP5_2_1.下列有关类的重用方法的叙述中,不正确的是( )。 A.类的继承可以实现类的重用 B.类的组合可以实现类的重用 C.类的封装可以实现类的重用 D.类的继承和类的组合都可…...

SATA数据线

SATA 数据线&#xff08;Serial ATA 数据线&#xff09;是一种用于连接计算机主板与存储设备&#xff08;如硬盘、固态硬盘和光驱&#xff09;的线缆。它的主要作用是传输数据&#xff0c;允许计算机与这些设备之间进行高效的数据交换。 主要作用 数据传输&#xff1a;SATA 数…...

《云原生安全攻防》-- K8s攻击案例:权限维持的攻击手法

在本节课程中&#xff0c;我们将一起深入了解K8s权限维持的攻击手法&#xff0c;通过研究这些攻击手法的技术细节&#xff0c;来更好地认识K8s权限维持所带来的安全风险。 在这个课程中&#xff0c;我们将学习以下内容&#xff1a; K8s权限维持&#xff1a;简单介绍K8s权限维持…...

回溯算法-Java【力扣】【算法学习day.14】

前言 ###我做这类文档一个重要的目的还是给正在学习的大家提供方向&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非常非常高滴&am…...

从本地到云端:跨用户请求问题的完美解决方案

对于某些单个请求或响应中含有多个用户信息的服务&#xff0c;SDK提供了一套基于统一的UCS拆分和聚合的解决方案供开发者使用。 请求拆分 对于跨用户服务的请求&#xff0c;我们提供了两个处理方案&#xff1a; 【1】根据用户信息拆分请求&#xff1a; 场景&#xff1a;请求内…...

leetcode day4 409+5

409 最长回文串 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的 回文串 的长度。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串。 示例 1: 输入:s "abccccdd" 输出:7 解…...

英语语法学习框架(考研)

一、简单句 英语都是由简单句构成&#xff0c;简单句共有五种基本句型&#xff1a;①主谓&#xff1b;②主谓宾&#xff1b;③主谓宾宾补&#xff1b;④主谓宾间宾&#xff08;间接宾语&#xff09;&#xff1b;⑤主系表&#xff1b; 其中谓语是句子最重要的部分&#xff0c;谓…...

基于neo4j的学术论文关系管理系统

正在为毕业设计头疼&#xff1f;又或者在学术研究中总是找不到像样的工具来管理浩瀚的文献资料&#xff1f;今天给大家介绍一款超实用的工具——基于Neo4j的学术论文关系管理系统&#xff0c;让你轻松搞定学术文献的管理与展示&#xff01;&#x1f389; 系统的核心是什么呢&a…...

C#中的委托、匿名方法、Lambda、Action和Func

委托 委托概述 委托是存有对某个方法的引用的一种引用类型变量。定义方法的类型&#xff0c;可以把一个方法当作另一方法的参数。所有的委托&#xff08;Delegate&#xff09;都派生自 System.Delegate 类。委托声明决定了可由该委托引用的方法。 # 声明委托类型 委托类型声…...

IDEA关联Tomcat——最新版本IDEA 2024

1.链接Tomcat到IDEA上 添加Tomcat到IDEA上有两种方式&#xff1a; 第一种&#xff1a; &#xff08;1&#xff09;首先&#xff0c;来到欢迎界面&#xff0c;找到左侧的Customize选项 &#xff08;2&#xff09;然后找到Build、Execution、Deployment选项 &#xff08;3&am…...

【如何获取股票数据18】Python、Java等多种主流语言实例演示获取股票行情api接口之沪深A股解禁限售数据获取实例演示及接口API说明文档

最近一两年内&#xff0c;股票量化分析逐渐成为热门话题。而从事这一领域工作的第一步&#xff0c;就是获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息&#xff0c;这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的主要任…...

NVR小程序接入平台/设备EasyNVR多品牌NVR管理工具/设备的多维拓展与灵活应用

在数字化安防时代&#xff0c;NVR批量管理软件/平台EasyNVR作为一种先进的视频监控系统设备&#xff0c;正逐步成为各个领域监控解决方案的首选。NVR批量管理软件/平台EasyNVR作为一款基于端-边-云一体化架构的国标视频融合云平台&#xff0c;凭借其部署简单轻量、功能多样、兼…...

GPT-4o 和 GPT-4 Turbo 模型之间的对比

GPT-4o 和 GPT-4 Turbo 之间的对比 备注 要弄 AI &#xff0c;不同模型之间的对比就比较重要。 GPT-4o 是 GPT-4 Turbo 的升级版本&#xff0c;能够提供比 GPT-4 Turbo 更多的内容和信息&#xff0c;但成功相对来说更高一些。 第三方引用 在 2024 年 5 月 13 日&#xff0…...

gin入门教程(10):实现jwt认证

使用 github.com/golang-jwt/jwt 实现 JWT&#xff08;JSON Web Token&#xff09;可以有效地进行用户身份验证,这个功能往往在接口前后端分离的应用中经常用到。以下是一个基本的示例&#xff0c;演示如何在 Gin 框架中实现 JWT 认证。 目录结构 /hello-gin │ ├── cmd/ …...

Python 基础语法 - 数据类型

顾名思义&#xff0c;计算机就是用来做数学计算的机器&#xff0c;因此&#xff0c;计算机程序理所当然的可以处理各种数值。但是&#xff0c;计算机能处理的远远不止数值&#xff0c;还可以处理文本&#xff0c;图形&#xff0c;音频&#xff0c;视频&#xff0c;网页等各种各…...

自托管无代码数据库Undb

什么是 Undb &#xff1f; Undb 是一个无代码平台&#xff0c;也可以作为后端即服务 (BaaS)。它基于 SQLite&#xff0c;可以使用 Bun 打包成二进制文件用于后端服务。此外&#xff0c;它可以通过 Docker 部署为服务&#xff0c;提供表管理的 UI。 软件特点&#xff1a; ⚡ 无…...

正则的正向前瞻断言和负向前瞻断言

正则的正向前瞻断言和负向前瞻断言 一. 正向前瞻断言二. 负向前瞻断言三. 总结 这是我在这个网站整理的笔记,有错误的地方请指出&#xff0c;关注我&#xff0c;接下来还会持续更新。 作者&#xff1a;神的孩子都在歌唱 正向前瞻断言和负向前瞻断言是正则表达式中用于检查后续字…...

大厂物联网(IoT)高频面试题及参考答案

目录 解释物联网 (IoT) 的基本概念 物联网的主要组成部分有哪些? 描述物联网的基本架构。 IoT 与传统网络有什么区别? 物联网中常用的传感器类型有哪些? 描述物联网的三个主要层次。 简述物联网中数据安全的重要性 描述物联网安全的主要威胁 解释端到端加密在 IoT 中…...

react hook

react hook 最近实习有点忙&#xff0c;所以学习记录没来得及写。 HOC higher order components(HOC) 高阶组件是一个组件&#xff0c;接受一个参数作为组件&#xff0c;返回值也是一个组件的函数。高阶组件作用域强化组件&#xff0c;服用逻辑&#xff0c;提升渲染性能等。…...

Jetpack架构组件_LiveData组件

1.LiveData初识 LiveData:ViewModel管理要展示的数据&#xff08;VM层类似于原MVP中的P层&#xff09;&#xff0c;处理业务逻辑&#xff0c;比如调用服务器的登陆接口业务。通过LiveData观察者模式&#xff0c;只要数据的值发生了改变&#xff0c;就会自动通知VIEW层&#xf…...

Etcd 可观测最佳实践

简介 Etcd 是一个高可用的分布式键值存储系统&#xff0c;它提供了一个可靠的、强一致性的存储服务&#xff0c;用于配置管理和服务发现。它最初由 CoreOS 开发&#xff0c;现在由 Cloud Native Computing Foundation (CNCF) 维护。Etcd 使用 Raft 算法来实现数据的一致性&…...

钉钉录播抓取视频

爬取钉钉视频 免责声明 此脚本仅供学习参考&#xff0c;切勿违法使用下载他人资源进行售卖&#xff0c;本人不但任何责任! 仓库地址: GItee 源码仓库 执行顺序 poxyM3u8开启代理getM3u8url用于获取m3u8文件userAgent随机请求头downVideo|downVideoThreadTqdm单线程下载和…...

centos下面的jdk17的安装配置

文章目录 1.基本指令回顾2.jdk17的安装到这个centos上面2.1首先切换到这个root下面去2.2查看系统jdk版本2.3首先到官网找到进行下载2.4安装包的上传2.5jdk17的安装包的解压过程2.6配置环境变量2.7是否设置成功&#xff0c;查看版本 1.基本指令回顾 ls:list也就是列出来这个目录…...

【操作系统】——调度

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 处理机调度的概念、层次 进程调度的时机、切换与过程、方式 调度器和闲逛进程 处理机调度的概念、层…...

移动免费网站建设/今日国际新闻头条

王阳明&#xff1a;人生即修行 笔记 少说多听&#xff0c;必有收获 人的心灵成长地图要求我们&#xff0c;必须要随时更正自己的前进方向&#xff0c;不能更正&#xff0c;或是拒绝更正心灵成长路线图的人只能困在原地&#xff0c;永远绕弯。 心阳光&#xff0c;世界不会黑暗…...

wordpress主题更新教程/网站优化培训学校

概念整理汇总&#xff1a;1.专业术语&#xff1a;CH4&#xff1a;曲率&#xff1a;曲线的曲率(curvature)就是针对曲线上某个点的切线方向角对弧长的转动率&#xff0c;通过微分来定义&#xff0c;表明曲线偏离直线的程度。数学上表明曲线在某一点的弯曲程度的数值。曲率越大&a…...

wordpress3.0 主题/seo的重要性

最近做前后端项目&#xff0c;前端项目启动需要切换到指定目录下&#xff0c;然后执行&#xff1a;npm run dev&#xff0c;进行启动。但是每次重启Idea之后打开Terminal都是项目的根目录&#xff0c;需要切换一下&#xff0c;比较麻烦&#xff0c;百度了一下&#xff0c;没找到…...

网站做跳转付款/广州网站优化推广方案

...

学编程可以建设网站吗/百度新闻搜索

1.找到页面元素obj 2.设置obj.style A. 直接写css属性,如&#xff1a;obj.style.height/width/color B. 改大写&#xff08;驼峰&#xff09;&#xff0c;如&#xff1a;obj.style.fontSize/marginLeft C. 浮动需要注意&#xff1a;obj.style[cssFloat in obj.style?cssFloat…...

wordpress网站怎么百度的到/网站流量排名查询工具

本文原址&#xff1a;http://www.hbzxr.com/web/36/2027736-1138928.htmljava this和super关键字 有什么作用成员函数中定义了和成员变量中相同的变量时&#xff0c;引用成员变量要用this. 构造函数中调用同一个类的其他构造函数时用this 子类中覆盖了于父类成员变量或成员函数…...