1. 初始化vue3项目
npm init @vitejs/app vue3-demo
加入文件夹,运行即可看到初始页面
npm i
npm run dev
初始化项目后配置文件目录如下
2. 配置tsconfig.json文件
{
"compilerOptions": {
"target": "esnext",
"useDefineForClassFields": true,
"module": "esnext",
"moduleResolution": "node",
"strict": true,
"jsx": "preserve",
"sourceMap": true,
"resolveJsonModule": true,
"esModuleInterop": true,
"lib": ["esnext", "dom"],
"baseUrl": "./",
"paths": {
"@":["src"],
"@/*":["src/*"],
},
"types": ["vite/client"]
},
"include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue"]
}
3. vite.config.ts
配置alias可简化路径,注:在tsconfig.json文件中有相应配置
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
const path = require('path');
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': path.resolve(__dirname, 'src'),
}
},
server: {
proxy: {
'/api': {
target: '目标地址',
ws: true,
changeOrigin: true,
// rewrite: path => path.replace(/^\/api/, ""),
},
},
},
});
注:配置好文件有有些地方可能会出现vscode报错,建议卸载vetur,安装vue languahe features插件
配置好基础文件后,可配置src内容
安装插件axios,antdv,echarts,配置路由
npm i --save ant-design-vue@next
npm i axios
npm i echarts
npm install vue-router@next --save
main.ts配置:
import { createApp } from 'vue'
import '@/assets/css/index.scss'
import App from './App.vue'
// element
// import ElementPlus from 'element-plus';
// import 'element-plus/dist/index.css'
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';
// 路由
import router from '@/router'
// // vuex
import store from "@/store";
// // 混入方法
import baseMixin from '@/utils/mixin'
// 请求接口
import {getRes} from "@/api/req";
// echarts
import * as echarts from 'echarts'
const app = createApp(App)
app
.use(router)
.use(store)
.mixin(baseMixin)
// .use(ElementPlus)
.use(Antd)
.mount('#app')
app.config.globalProperties.$echarts = echarts
app.config.globalProperties.$getRes = getRes
app.config.globalProperties.$getAEDRes = getAEDRes
// createApp(App).mount('#app')
router.ts配置
import { createRouter, createWebHashHistory } from 'vue-router'
interface routerList {
path:string
name:string
component:any
children?:routerList[]
}
const routes= >[
{
path: '/',
name: 'Login',
component: () => import('@/views/Login.vue')
},
{
path: '/Login',
name: 'Login',
component: () => import('@/views/Login.vue')
},
{
path: '/Index',
name: 'Index',
component: () => import('@/views/Index.vue'),
children:[
{
path: '/',
name: 'TableManage',
component: () => import('@/views/menu/TableManage.vue')
},
{
path: '/TableManage',
name: 'TableManage',
component: () => import('@/views/menu/TableManage.vue')
},
]
},
{
path: '/:pathMatch(.*)*', // 捕获所有路由或 404 Not found 路由, 可在括号中加入自定义正则表达式
component: () => import('@/views/Page404.vue')
}
]
const router = createRouter({
history: createWebHashHistory(), // 可以换模式
routes
})
// 路由守卫
router.beforeEach((to,from,next)=>{
if (to.path === '/Login') return next()
// 获取用户本地的token, 如果token不存在则跳转到登录页
const tokenStr = sessionStorage.getItem('token')
if (!tokenStr) return next('/Login')
next()
});
export default router
axios中配置
axios/index.ts
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import { errorCodeType } from './error-code-type';
import { message } from 'ant-design-vue';
// 创建axios实例
const service = axios.create(<{
baseURL:any
timeout:number
headers:any
}>{
// 服务接口请求
baseURL: import.meta.env.VITE_APP_BASE_API,
// 超时设置
timeout: 15000,
headers:{'Content-Type':'application/json;charset=utf-8'}
})
let loading:any;
//正在请求的数量
let requestCount:number = 0
//显示loading
const showLoading = () => {
if (requestCount === 0 && !loading) {
// loading = ElLoading.service({
// text: "拼命加载中,请稍后...",
// background: 'rgba(0, 0, 0, 0.7)',
// spinner: 'el-icon-loading',
// })
}
requestCount++;
}
//隐藏loading
const hideLoading = () => {
requestCount--
if (requestCount == 0) {
loading.close()
}
}
// 请求拦截
service.interceptors.request.use((config: AxiosRequestConfig) => {
// showLoading()
config.headers['token'] = sessionStorage.getItem("token") // 让每个请求携带自定义token 请根据实际情况自行修改
// get请求映射params参数
if (config.method === 'get' && config.params) {
let url = config.url + '?';
for (const propName of Object.keys(config.params)) {
const value = config.params[propName];
var part = encodeURIComponent(propName) + "=";
if (value !== null && typeof(value) !== "undefined") {
if (typeof value === 'object') {
for (const key of Object.keys(value)) {
let params = propName + '[' + key + ']';
var subPart = encodeURIComponent(params) + "=";
url += subPart + encodeURIComponent(value[key]) + "&";
}
} else {
url += part + encodeURIComponent(value) + "&";
}
}
}
url = url.slice(0, -1);
config.params = {};
config.url = url;
}
return config
}, error => {
console.log(error)
Promise.reject(error)
})
// 响应拦截器
service.interceptors.response.use((res:AxiosResponse) => {
hideLoading()
// 未设置状态码则默认成功状态
const code = res.data['code'] || 200;
// 获取错误信息
const msg = errorCodeType(code) || res.data['msg'] || errorCodeType('default')
if(code === 200){
return Promise.resolve(res.data)
}else{
message.error(msg)
return Promise.reject(res.data)
}
},
(error: AxiosError) => {
console.log('err' + error)
hideLoading()
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) + "异常";
}
message.error(msg,5 * 1000)
return Promise.reject(error)
}
)
export default service;
axios/error-code-type.ts配置
export const errorCodeType = function(code:string):string{
let msg:string = ""
switch (code) {
case "401":
msg = '认证失败,无法访问系统资源'
break;
case "403":
msg = '当前操作没有权限'
break;
case "404":
msg = '访问资源不存在'
break;
case "default":
msg = '系统未知错误,请反馈给管理员'
break;
// case 400:
// error.message = '请求错误'
// break
// case 401:
// break
// case 402:
// break
// case 403:
// error.message = `身份已失效,请重新登录`
// window.location.href = '../sys-nt/login.html'
// break
// case 404:
// error.message = `请求地址出错: ${error.response.config.url}`
// break
// case 408:
// error.message = '请求超时'
// break
// case 500:
// error.message = '服务器内部错误'
// break
// case 501:
// error.message = '服务未实现'
// break
// case 502:
// error.message = '网关错误'
// break
// case 503:
// error.message = '服务不可用'
// break
// case 504:
// error.message = '网关超时'
// break
// case 505:
// error.message = 'HTTP版本不受支持'
// break
default:
return '未知错误,请联系管理员'
}
return msg
}
接下来就可以配置api文件夹内容,main.js中引入变成全局方法,就不用每个页面都引入了
api/req.ts
// url:请求地址
// method:请求方法
// data:请求参数
// decide:判断接口数据是否获取成功的条件
import request from '@/axios'
import { message } from 'ant-design-vue';
interface urldata {
[index:string]:any
}
export function getRes(url:string,method:string,data?:any,decide?:string):any{
let decideC:string = decide?decide:'error_code'
let apidata = {
url: '/api' + url,
method: method,
}
if(method == 'get') apidata.params = data
if(method == 'post') apidata.data = data
return new Promise((resolve:any, reject:any) => {
request({...apidata}).then((res:any)=>{
if(res[decideC] == 0) {
return resolve(res);
}else {
message.error(res.message)
return resolve(res)
}
}).catch(err=>{
// Message.error(err)
return resolve(err)
})
})
}
配置完axios在页面中可直接使用
import { Ref,ref, watch, watchEffect,getCurrentInstance } from 'vue'
let { proxy } = getCurrentInstance() as any
proxy.$getRes('/captcha','get').then((res:any)=>{
if(res.error_code === 0){
// 成功
}else{
// 失败
}
})
App.vue 可在此处配置插件中文
至此项目配置就结束了,可以在view中写页面了