1.基础准备
uni-app官网uni-app,uniCloud,serverless,环境安装,创建uni-app,自定义模板,国内特殊情况,更新依赖到指定版本,运行、发布uni-app,运行并发布快应用,运行并发布快应用(webview),运行并发布快应用(webview)-华为,cli创建项目和HBuilderX可视化界面创https://uniapp.dcloud.net.cn/quickstart-cli.html 安装node、hbuilder
安装pnpm,相比于npm他的优点是:显著提升了包安装的速度和磁盘空间利用率,同时避免了依赖冲突和重复安装的问题;
npm install -g pnpm
创建uniapp vue3+ts项目
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
2.引入uni-ui 组件库
安装 uni-ui 组件库
pnpm i @dcloudio/uni-ui
src/pages.json
// pages.json
{// 组件自动导入"easycom": {"autoscan": true,"custom": {// uni-ui 规则如下配置 // [!code ++]"^uni-(.*)": "@dcloudio/uni-ui/lib/uni-$1/uni-$1.vue" // [!code ++]}},"pages": [// …省略]
}
安装类型声明文件
pnpm i -D @uni-helper/uni-ui-types
配置类型声明文件
// tsconfig.json
{"compilerOptions": {// ..."types": ["@dcloudio/types", // uni-app API 类型"miniprogram-api-typings", // 原生微信小程序类型"@uni-helper/uni-app-types", // uni-app 组件类型"@uni-helper/uni-ui-types" // uni-ui 组件类型 // [!code ++]]},// vue 编译器类型,校验标签类型"vueCompilerOptions": {"nativeTags": ["block", "component", "template", "slot"]}
}
3.小程序端 Pinia 持久化
安装持久化存储插件,pinia-plugin-persistedstate
pnpm i pinia-plugin-persistedstate
src/stores/modules/member.ts
import type { LoginResult } from '@/types/member'
import { defineStore } from 'pinia'
import { ref } from 'vue'// 定义 Store
export const useMemberStore = defineStore('member',() => {// 会员信息const profile = ref<LoginResult>()// 保存会员信息,登录时使用const setProfile = (val: LoginResult) => {profile.value = val}// 清理会员信息,退出时使用const clearProfile = () => {profile.value = undefined}// 记得 returnreturn {profile,setProfile,clearProfile,}},{// 网页端配置// persist: true,// 小程序端配置persist: {storage: {getItem(key) {return uni.getStorageSync(key)},setItem(key, value) {uni.setStorageSync(key, value)},},},},
)
src/stores/index.ts
import { createPinia } from 'pinia'
import persist from 'pinia-plugin-persistedstate'// 创建 pinia 实例
const pinia = createPinia()
// 使用持久化存储插件
pinia.use(persist)// 默认导出,给 main.ts 使用
export default pinia// 模块统一导出
export * from './modules/member'
src/main.ts
import { createSSRApp } from 'vue'
import App from './App.vue'// 导入 pinia 实例
import pinia from './stores'export function createApp() {// 创建 vue 实例const app = createSSRApp(App)// 使用 piniaapp.use(pinia)return {app,}
}
4.uni.request 请求封装
创建拦截器,src/utils/http.ts
/*** 添加拦截器:* 拦截 request 请求* 拦截 uploadFile 文件上传** TODO:* 1. 非 http 开头需拼接地址* 2. 请求超时* 3. 添加小程序端请求头标识* 4. 添加 token 请求头标识*/import { useMemberStore } from '@/stores'const baseURL = 'https://pcapi-xiaotuxian-front-devtest.itheima.net'// 添加拦截器
const httpInterceptor = {// 拦截前触发invoke(options: UniApp.RequestOptions) {// 1. 非 http 开头需拼接地址if (!options.url.startsWith('http')) {options.url = baseURL + options.url}// 2. 请求超时, 默认 60soptions.timeout = 10000// 3. 添加小程序端请求头标识options.header = {...options.header,'source-client': 'miniapp',}// 4. 添加 token 请求头标识const memberStore = useMemberStore()const token = memberStore.profile?.tokenif (token) {options.header.Authorization = token}},
}
uni.addInterceptor('request', httpInterceptor)
uni.addInterceptor('uploadFile', httpInterceptor)/*** 请求函数* @param UniApp.RequestOptions* @returns Promise* 1. 返回 Promise 对象* 2. 获取数据成功* 2.1 提取核心数据 res.data* 2.2 添加类型,支持泛型* 3. 获取数据失败* 3.1 401错误 -> 清理用户信息,跳转到登录页* 3.2 其他错误 -> 根据后端错误信息轻提示* 3.3 网络错误 -> 提示用户换网络*/
type Data<T> = {code: stringerrorMessage: stringdata: T
}
// 2.2 添加类型,支持泛型
export const http = <T>(options: UniApp.RequestOptions) => {// 1. 返回 Promise 对象return new Promise<Data<T>>((resolve, reject) => {uni.request({...options,// 响应成功success(res) {// 状态码 2xx, axios 就是这样设计的if (res.statusCode >= 200 && res.statusCode < 300) {// 2.1 提取核心数据 res.dataresolve(res.data as Data<T>)} else if (res.statusCode === 401) {// 401错误 -> 清理用户信息,跳转到登录页const memberStore = useMemberStore()memberStore.clearProfile()uni.navigateTo({ url: '/user/login' })reject(res)} else {// 其他错误 -> 根据后端错误信息轻提示uni.showToast({icon: 'none',title: (res.data as Data<T>).errorMessage || '请求错误',})reject(res)}},// 响应失败fail(err) {uni.showToast({icon: 'none',title: '网络错误,换个网络试试',})reject(err)},})})
}
6.统一代码风格
安装 eslint+prettier
pnpm i -D eslint prettier eslint-plugin-vue @vue/eslint-config-prettier @vue/eslint-config-typescript @rushstack/eslint-patch @vue/tsconfig
新建文件.eslintrc.cjs ,添加以下 eslint 配置
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')module.exports = {root: true,extends: ['plugin:vue/vue3-essential','eslint:recommended','@vue/eslint-config-typescript','@vue/eslint-config-prettier',],// 小程序全局变量globals: {uni: true,wx: true,WechatMiniprogram: true,getCurrentPages: true,UniApp: true,UniHelper: true,},parserOptions: {ecmaVersion: 'latest',},rules: {'prettier/prettier': ['warn',{singleQuote: true,semi: false,printWidth: 100,trailingComma: 'all',endOfLine: 'auto',},],'vue/multi-word-component-names': ['off'],'vue/no-setup-props-destructure': ['off'],'vue/no-deprecated-html-element-is': ['off'],'@typescript-eslint/no-unused-vars': ['off'],},
}
配置package.json
{"script": {// ... 省略 ..."lint": "eslint . --ext .vue,.js,.ts --fix --ignore-path .gitignore"}
}
pnpm lint
7.Git 工作流规范
安装并初始化 husky
pnpm dlx husky-init
npx husky-init
安装 lint-staged
pnpm i -D lint-staged
配置package.json
{"script": {// ... 省略 ...},"lint-staged": {"*.{vue,ts,js}": ["eslint --fix"]}
}
修改 .husky/pre-commit
文件
#!/usr/bin/env sh
. "$(dirname -- "$0")/_/husky.sh"
pnpm lint-staged