vite+vue3+ts 前端后台项目学习笔记
1.vite
npm create vite@latest
1.1vite 路径别名 @ 配置
npm install @types/node --save-dev
Vite配置alias需要两步进行(TS项目)
1、修改vite.config.ts(让程序支持)
2、修改tsconfig.json(让编辑器支持)
vite.config.ts
import { resolve } from "path"
const pathResolve = (dir: string): any => {
return resolve(__dirname, ".", dir)
}
export default defineConfig({
...,
resolve: {
alias: {
"/@": pathResolve("./src/"),
assets: pathResolve("./src/assets"),
},
},
})
tsconfig.json
{
"compilerOptions": {
...
"baseUrl": "./",
"paths": {
"/@/*": ["src/*"]
}
},
// "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"],
"references": [{ "path": "./tsconfig.node.json" }],
"exclude": ["node_modules"]
}
2.router
2.1安装依赖
npm install vue-router
2.2项目引用
2.2.1挂载
import { createApp } from 'vue'
import App from './App.vue'
import router from "./router/index"
createApp(App).use(router).mount('#app')
2.2.2配置路由
在src下创建router/index.ts
import { createRouter, createWebHashHistory } from "vue-router"
import { staticRoutes } from "/@/router/static"
// 创建 router 实例,然后传 `routes` 配置
const router = createRouter({
history: createWebHashHistory(),
routes: staticRoutes,
})
// 每次跳转页面前显示进度条
router.beforeEach((to, from, next) => {
//全局进度条的配置
})
// 路由加载后隐藏进度条
router.afterEach(() => {
NProgress.done()
})
export default router
在src下创建router/static.ts
import { RouteRecordRaw } from "vue-router"
import Layout from "/@/layouts/index.vue"
/*
* 静态路由
*/
const staticRoutes: Array<RouteRecordRaw> = [
{
// 登录页
path: "/Login",
name: "/Login",
component: () => import("/@/views/login/login.vue"),
meta: {
title: "Login",
},
},
{
path: "/",
component: Layout,
children: [
{
path: "/dashboard",
component: () => import("/@/views/dashboard/dashboard.vue"),
meta: {
title: "首页",
},
},
{
path: "/about",
name: "About",
component: () => import("/@/views/about.vue"),
},
],
},
{
path: "/:path(.*)*",
redirect: "/404",
},
{
// 404
path: "/404",
name: "notFound",
component: () => import("/@/views/common/error/404.vue"),
meta: {
title: "notFound", // 页面不存在
},
},
{
// 无权限访问
path: "/401",
name: "noPower",
component: () => import("/@/views/common/error/401.vue"),
meta: {
title: "noPower",
},
},
]
export { staticRoutes }
2.2.3编程式路由导航 path
app.vue
<template>
<router-view></router-view>
</template>
<script setup lang="ts"></script>
<style scoped></style>
3.element-plus
3.1安装
npm install element-plus --save
3.2按需导入-自动导入
3.2.1安装插件
首先你需要安装unplugin-vue-components 和 unplugin-auto-import这两款插件
npm install -D unplugin-vue-components unplugin-auto-import
3.2.2配置插件
把下列代码插入到你的 Vite配置文件中vite.config.ts
// vite.config.ts
import { defineConfig } from 'vite'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'
export default defineConfig({
// ...
plugins: [
// ...
AutoImport({
resolvers: [ElementPlusResolver()],
}),
Components({
resolvers: [ElementPlusResolver()],
}),
],
})
3.2.3 图标
图标需要另外自己导入
安装:
npm install @element-plus/icons-vue
导入:在main.ts中注册所有图标(官方文档中有自动导入的方法,我试了,查了很多资料都没成功,放弃了)
// main.ts
// 如果您正在使用CDN引入,请删除下面一行。
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
const app = createApp(App)
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
app.component(key, component)
}
4.nprogress(进度条)
4.1安装本体
$ npm i nprogress
4.2安装插件
$ npm i @types/nprogress
4.3引入
import NProgress from 'nprogress'
import 'nprogress/nprogress.css'
4.4配置进度条
对进度条进行一些基础配置
//全局进度条的配置
NProgress.configure({
easing: 'ease', // 动画方式
speed: 1000, // 递增进度条的速度
showSpinner: false, // 是否显示加载ico
trickleSpeed: 200, // 自动递增间隔
minimum: 0.3, // 更改启动时使用的最小百分比
parent: 'body', //指定进度条的父容器
})
放在router中使用:
// router/index.ts
// 每次跳转页面前显示进度条
router.beforeEach((to, from, next) => {
//全局进度条的配置
NProgress.configure({
easing: "ease", // 动画方式
speed: 1000, // 递增进度条的速度
showSpinner: false, // 是否显示加载ico
trickleSpeed: 200, // 自动递增间隔
minimum: 0.3, // 更改启动时使用的最小百分比
parent: "body", //指定进度条的父容器
})
NProgress.start()
next()
})
// 路由加载后隐藏进度条
router.afterEach(() => {
NProgress.done()
})
4.5在Vue切换路由时展示进度条
现在我们就来使用我们上面封装的Nprogress,这里我们在VueRouter的配置文件中使用,实现切换路由时在顶部展示进度条,首先我们打开VueRouter的配置文件,然后引入我们封装的Nprogress:
// router/index.ts
import { close, start } from '/@/utils/nprogress'
然后我们在创建的Router实例中使用这两个方法:
beforeEach:路由切换之前触发;afterEach:路由切换完成后触发
const router = createRouter({
routes,
history: createWebHistory(),
})
router.beforeEach((pre, next) => {
start()
})
router.afterEach(() => {
close()
})
5.Axios
5.1安装
npm install axios
5.2封装方法
这个封装我重新写了个笔记:Vue 3 + TypeScript 封装 Axios 工具类 - 掘金 (juejin.cn)
我这里就贴个封装好的
在src/utils下封装一个axios.ts的方法
import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
enum ResponseCode {
Success = 0, // 请求成功
Unauthorized = 401, // 未授权
NotFound = 404, // 资源不存在
InternalServerError = 500, // 服务器内部错误
}
interface ResponseData<T = any> {
success: boolean;
code: ResponseCode;
message: string;
data?: T;
}
class AxiosService {
private axiosInstance: AxiosInstance
constructor() {
this.axiosInstance = axios.create({
baseURL: 'https://api.example.com',
timeout: 5000,
})
this.initInterceptor()
}
private initInterceptor() {
// 添加请求拦截器
this.axiosInstance.interceptors.request.use(
(config: AxiosRequestConfig) => {
// 在请求发送之前做些什么
const token = localStorage.getItem('token')
if (token) {
// 添加 token 到请求头
config.headers.Authorization = `Bearer ${token}`
}
return config
},
(error: any) => {
// 对请求错误做些什么
return Promise.reject(error)
}
)
// 添加响应拦截器
this.axiosInstance.interceptors.response.use(
(response: AxiosResponse<ResponseData>) => {
// 对响应数据做些什么
const { success, code, message, data } = response.data
if (!success || code !== ResponseCode.Success) {
// 请求失败或者出现错误
console.error(`[${code}] ${message}`)
return Promise.reject(new Error(message))
}
return data
},
(error: any) => {
// 对响应错误做些什么
if (error.response) {
// 如果服务器返回错误状态码
switch (error.response.status) {
case ResponseCode.Unauthorized:
// 未授权,跳转到登录页
break
case ResponseCode.NotFound:
// 请求的资源不存在
break
default:
// 其他错误
break
}
} else if (error.request) {
// 如果请求发出去没有收到响应
console.log(error.request)
} else {
// 其他错误
console.log('Error', error.message)
}
return Promise.reject(error)
}
)
}
public get<T = any>(url: string, config?: AxiosRequestConfig): Promise<T> {
return this.axiosInstance.get<T>(url, config)
}
public post<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.post<T>(url, data, config)
}
public put<T = any>(
url: string,
data?: any,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.put<T>(url, data, config)
}
public delete<T = any>(
url: string,
config?: AxiosRequestConfig
): Promise<T> {
return this.axiosInstance.delete<T>(url, config)
}
}
export const axiosService = new AxiosService()
5.3使用案例
登录api
import axios from "/@/utils/axios"
namespace Login {
// 用户登录表单
export interface LoginReqForm {
username: string
password: string
}
// 登录成功后返回的token
export interface LoginResData {
nickName: string
token: string
}
}
// 用户登录
export const login = (params: Login.LoginReqForm) => {
// 返回的数据格式可以和服务端约定
return axios.post<Login.LoginResData>("/auth/login", params)
}
// 用户登录
export const logout = () => {
// 返回的数据格式可以和服务端约定
return axios.get("/auth/logout")
}
6.pinia
6.1安装
$ npm install pinia
6.2引入
import { createPinia } from 'pinia'
app.use(createPinia())
持续更新中。。。。。。