创建项目
建议使用pnpm包管理器来创建项目,因为比同类工具更快,更节省空间

使用命令pnpm create vue
创建项目,根据需要选择所用的包,本次会使用到TypeScript、Router、Pinia、ESLint、Prettier
设置代码风格
ESLint:代码分析工具,用来检查代码质量
Prettier:代码格式化工具,例如保存时按照标准格式化进行保存
两者合并使用可以在 ESLint 检查代码质量的同时,自动应用 Prettier 的格式化规则。
VSCode提前安装ESLint
和Prettier - Code formatter
插件
设置项目根目录下.prettierrc.json
为{}
设置项目根目录下.eslintrc.cjs
为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| 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/skip-formatting' ], parserOptions: { ecmaVersion: 'latest' }, rules: { 'prettier/prettier': [ 'warn', { singleQuote: true, semi: false, printWidth: 80, trailingComma: 'none', endOfLine: 'auto' } ], 'vue/multi-word-component-names': [ 'warn', { ignores: ['index'] } ], 'vue/no-setup-props-destructure': ['off'] } }
|
注意:关闭vscode默认自动保存格式化,在.vscode/settings.json
中设置"editor.formatOnSave": false
设置完成后可以执行pnpm lint
对所有的文件进行格式标准化
目录调整

路由初始化
在router目录下增加index.ts文件
1 2 3 4 5 6 7 8 9
| import { createRouter, createWebHistory } from 'vue-router'
const router = createRouter({ history: createWebHistory(import.meta.env.BASE_URL), routes: [] }) console.log(import.meta) export default router
|
上面的BASE_URL默认路径,可以在vite.config.ts
中设置,不设置默认为/

在main.ts中引用路由
import router from './router'
app.use(router)
设置移动端适配
安装移动端库Vant,pnpm add vant
在main.ts中引入vant的css,注意要将styles/main.scss
文件放在后面,因为我们要将自定义的样式覆盖Vant的样式

进行移动端适配,安装:pnpm add postcss-px-to-viewport -D
新增postcss.config.js
文件
1 2 3 4 5 6 7
| export default { plugins: { 'postcss-px-to-viewport': { viewportWidth: 375 } } }
|
主题定制
我们可以声明css变量来进行主题定制

在style/main.css
中进行css声明变量
如果想要覆盖元件库中的主题,找到主题变量名,直接覆盖就可以

用户仓库和持久化
pinia建议独立维护
在stores中创建modules目录,在里面增加相应的仓库,如user.ts
安装自动持久化包:pnpm i pinia-plugin-persistedstate
首先要明确user的数据结构,并在types目录下增加user.d.ts
1 2 3 4 5 6 7
| export type User = { token: string id: string account: string mobile: string avatar: string }
|
定义user.ts仓库
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| import type { User } from '@/types/user' import { defineStore } from 'pinia' import { ref } from 'vue'
export const useUserStore = defineStore( 'cp-user', () => { const user = ref<User>() const setUser = (u: User) => { user.value = u } const delUser = () => { user.value = undefined } return { user, setUser, delUser } }, { persist: true } )
|
在stroes下的index.ts中,统一导出所有的仓库
1 2 3 4 5 6
| import { createPinia } from 'pinia' import presist from 'pinia-plugin-persistedstate'
export const pinia = createPinia().use(presist)
export * from './modules/user'
|
在main.ts中引入
import { pinia } from './stores'
app.use(pinia)
请求工具设定
在utils目录下增加request.ts
文件
1.首先设置基础信息
2.设置请求拦截器
3.设置响应拦截器
4.封装请求函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| import router from '@/router' import { useUserStore } from '@/stores' import axios, { AxiosError, type Method } from 'axios' import { showToast } from 'vant'
export const baseURL = 'https://xxx/'
const instance = axios.create({ baseURL, timeout: 10000 })
instance.interceptors.request.use( (config) => { const store = useUserStore() if (store.user?.token && config.headers) { config.headers.Authorization = `Bearer ${store.user.token}` } return config }, (err) => Promise.reject(err) )
instance.interceptors.response.use( (res) => { if (res.data.code !== 10000) { showToast(res.data.message || '业务失败') return Promise.reject(res.data) } return res.data }, (err: AxiosError) => { if (err.response?.status === 401) { const store = useUserStore() store.delUser() router.push({ path: '/login', query: { returnUrl: router.currentRoute.value.fullPath } }) } return Promise.reject(err) } )
export default instance
type Data<T> = { code: number message: string data: T }
export const request = <T>( url: string, method: Method = 'GET', submitData?: object ) => { return instance.request<any, Data<T>>({ url, method, [method.toUpperCase() === 'GET' ? 'params' : 'data']: submitData }) }
|
使用请求工具
