赞
踩
安装pnpm,相比于npm他的优点是:显著提升了包安装的速度和磁盘空间利用率,同时避免了依赖冲突和重复安装的问题;
npm install -g pnpm
创建uniapp vue3+ts项目
npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project
安装 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"]
- }
- }
安装持久化存储插件,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
- }
-
- // 记得 return
- return {
- 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)
-
- // 使用 pinia
- app.use(pinia)
-
- return {
- app,
- }
- }
创建拦截器,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. 请求超时, 默认 60s
- options.timeout = 10000
- // 3. 添加小程序端请求头标识
- options.header = {
- ...options.header,
- 'source-client': 'miniapp',
- }
- // 4. 添加 token 请求头标识
- const memberStore = useMemberStore()
- const token = memberStore.profile?.token
- if (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: string
- errorMessage: string
- data: 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.data
- resolve(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)
- },
- })
- })
- }
安装 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(eslint8版本--ext命令不支持,用下面的)
- {
- "script": {
- // ... 省略 ...
- "lint": "eslint . --ext .vue,.js,.ts --fix --ignore-path .gitignore"
- }
- }
- {
- "scripts": {
- // ... 省略 ...
- "lint": "eslint . --fix --ignore-path .gitignore"
- }
- }
pnpm lint
安装并初始化 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。