使用vue-ts模板创建项目
npm create vite my-vue-app --template vue-ts
项目目录截图
npm install vue-router@4 -S
2.2.1、在src创建router文件夹并且在router文件夹下创建index.ts文件
import { createRouter, createWebHistory, RouteRecordRaw } from "vue-router";
const routes: Array = [
{
path: "/",
name: "home",
/** 在src/views 文件下创建home文件 */
component: () => import("../views/home/index.vue"),
},
{
path: "/about",
name: "about",
/** 在src/views 文件下创建about文件 */
component: () => import("../views/about/index.vue"),
},
];
const router = createRouter({
history: createWebHistory(),
routes,
});
export default router;
2.2.2、在main.ts文件中添加router引用
import { createApp } from 'vue'
/** --- 新增代码块 start --- */
import router from './router';
/** --- 新增代码块 end --- */
import './style.css'
import App from './App.vue'
/** --- 修改代码块 end --- */
const app = createApp(App);
app.use(router);
app.mount('#app')
/** --- 修改代码块 start --- */
2.2.3、修改App.vue,删除之前代码,改成如下代码块
npm install vuex -S
3.2.1、在src下创建store文件夹并在store文件夹下创建index.ts文件、getters.ts文件、modules文件夹
// index.ts 文件配置
import { createStore } from "vuex";
import type { App } from "vue";
import getters from "./getters";
// 获取modules文件夹中所有ts文件
const modulesFiles = import.meta.globEager('./modules/*.ts');
const modules: any = {};
interface Module {
default: object
}
/**
* 不需要import app from ./modules/app
* 它将自动从模块文件中要求所有的vuex模块
*/
Object.keys(modulesFiles).forEach(fileName => {
const name = fileName.replace(/^\.\/modules\/(.*)\.\w+$/, "$1");
modules[name] = (modulesFiles[fileName] as Module).default;
})
// 手动声明 state 类型
export interface State { }
const store = createStore({
// 使用模块
modules,
getters,
});
export default store;
// getters.ts 文件
const getters = {}
export default getters;
3.2.2、在modules文件夹下创建users.ts(你可以创建自己需要的文件)
export interface State { }
const state = () => ({});
const mutations = {};
const actions = {}
export default {
namespaced: false,
state,
mutations,
actions,
}
3.2.3、在main.ts文件中添加store引用
import { createApp } from 'vue'
/** --- 新增代码 start --- */
import store from './store'
/** --- 新增代码 end --- */
import router from './router'
import './style.css'
import App from './App.vue'
const app = createApp(App)
/** --- 新增代码 start --- */
app.use(store)
/** --- 新增代码 end --- */
app.use(router)
app.mount('#app')
npm install axios -S
4.2.1、配置封装axios,这边把封装的axios放在了src/utils/request 目录下,分别创下一下文件
export default {
'401': '认证失败,无法访问系统资源',
'403': '当前操作没有权限',
'404': '访问资源不存在',
'default': '系统未知错误,请反馈给管理员'
}
import axios from 'axios'
import { Modal, message, notification } from 'ant-design-vue'
import errorCode from '@/utils/request/errorCode'
// import { getToken } from '@/utils/auth' // 后续登录的token
// 是否显示重新登录
export const isRelogin = { show: false }
// axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8'
// 创建axios实例
const service = axios.create({
// axios中请求配置有baseURL选项,表示请求URL公共部分
baseURL: import.meta.env.VITE_BASE_URL,
// 超时
timeout: 10000
})
// request拦截器
service.interceptors.request.use(config => {
// 是否需要设置 token
// const isToken = (config.headers || {}).isToken === false
// if (getToken() && !isToken && config && config?.headers) {
// config.headers['Authorization'] = 'Bearer ' + getToken() // 让每个请求携带自定
// 义token 请根据实际情况自行修改
//}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use(res => {
// 未设置状态码则默认成功状态
const code = res.data.code
// 获取错误信息
const msg: string = errorCode[code as keyof typeof errorCode] || res.data.msg || errorCode['default']
// 二进制数据则直接返回
if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
return res.data
}
if (code === 401) {
if (!isRelogin.show) {
isRelogin.show = true
Modal.warning({
title: '系统提示',
content: '登录状态已过期,请重新登录',
onOk() {
isRelogin.show = false
location.href = '/login'
},
onCancel() {
isRelogin.show = false
location.href = '/login'
}
})
}
return Promise.reject('无效的会话,或者会话已过期,请重新登录。')
} else if (code === 500) {
message.error(msg)
return Promise.reject(new Error(msg))
} else if (code !== 200) {
notification.error({
message: msg
})
return Promise.reject('error')
} else {
return res.data
}
},
error => {
let msg = error.message
if (msg == 'Network Error') {
msg = '后端接口连接异常'
} else if (msg.includes('timeout')) {
msg = '系统接口请求超时'
} else if (msg.includes('Request failed with status code')) {
msg = '系统接口' + msg.substr(msg.length - 3) + '异常'
}
console.log(msg);
message.error(msg)
return Promise.reject(msg)
}
)
export default service
import axios from './axios'
/**
* 将Object数据转换成字符串拼接数据(格式为?a=a&b=b)
* @param {*} params
* @returns
*/
const getParamsStr = (params: any) => {
let paramstr = ''
const param = params || {}
if (param) {
let index = 0
for (const key in param) {
if (index > 0) {
paramstr += '&'
}
paramstr += key + '=' + encodeURI(param[key])
index++
}
}
if (paramstr.length > 0) {
// paramstr = '?' + paramstr;
}
return paramstr
}
export default {
/**
* get方法,对应get请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
get: (url: string, params?: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.get(url, {
params: params || '',
headers
})
.then((res: any) => {
resolve(res)
})
.catch((err: string) => {
reject(err)
})
})
},
/**
* post方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
post: (url: string, params?: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.post(url, params, {
headers: {
...headers,
'Content-Type': 'application/json;charset=UTF-8'
}
})
.then((res: any) => {
resolve(res)
})
.catch((err: string) => {
reject(err)
})
})
},
/**
* formPost方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
formPost: (url: string, params: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.post(url, getParamsStr(params), {
headers: {
...headers,
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
}
})
.then((res: any) => {
resolve(res)
})
.catch((err: string) => {
reject(err)
})
})
},
/**
* formDataPost方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
formDataPost: (url: string, params?: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.post(url, params, {
headers: {
headers,
'Content-Type': 'multipart/form-data'
}
})
.then(res => {
resolve(res.data)
})
.catch(err => {
reject(err.data)
})
})
},
/**
* delete方法,对应post请求
* @param {String} url [请求的url地址]
* @param {Object} params [请求时携带的参数]
*/
delete: (url: string, params?: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.delete(url, {
params: params || '',
headers
})
.then((res: any) => {
resolve(res)
})
.catch((err: string) => {
reject(err)
})
})
},
/**
* put请求
* @param url 接口路由
* @param data 接口参数
* @param auth 是否需要带登录信息
* @returns {AxiosPromise}
*/
put: (url: string, params?: any, headers?: any) => {
headers = headers || { isToken: true }
return new Promise((resolve, reject) => {
axios
.put(url, params, {
headers: {
...headers,
'Content-Type': 'application/json;charset=UTF-8'
}
})
.then((res: any) => {
resolve(res)
})
.catch((err: string) => {
reject(err)
})
})
},
download: (url: string, params: any, filename: string) => {
return new Promise((resolve, reject) => {
console.log(url, filename)
resolve(1)
reject(2)
})
}
}
4.3.1、创建api目录,(建议:分模块使用接口,这边案例使用的是login.ts)
import request from '@/utils/request'
import { LoginParams } from '@/constants/params/login' // 在公共目录下创建api参数对应的数据类型
// 登录方法
export function login(params: LoginParams) {
return request.post('/login', params, { isToken: false })
}
constants/params 目录下的 login.ts
export interface LoginParams {
username: string,
password: string,
rememberMe: boolean,
code: string,
uuid: string
}