一、Vue基本概念
1.1-Vue3的优点
- Vue3支持Vue2额大多数特性。
- 更好的支持TypeScript。
- 打包大小减少41%。
- 初次渲染快55%,更新渲染快133%。
- 内存减少54%。
- 使用proxy代替defineProperty实现数据响应式。
- 重写虚拟DOM的实现和Tree-Shaking。
二、API
2.1-setup
我们可以跟以前定义data和methods,但是vue3中我们更推荐使用setup函数。
- setup是一个函数。只在初始化时执行一次。以后大部分代码都是在setup中写。
- 返回一个对象,对象中的属性或方法,模板中可以直接使用。
- setup返回的数据会和data和methods进行合并,setup优先级更高。
- setup函数中没有this。 以后开发都不使用this了
- setup不要写async函数。
因为async函数必须返回一个json对象供模板使用,如果setup是一个async函数,返回的将是一个promise对象。
如果setup是一个async函数,那该组件就成了一个异步函数,需要配合Suspense组件才能使用。
2.2-ref
让数据变成响应式。
(1)先引用ref
import {ref} from 'vue';
(2)将数据变成响应式的。
let data1=ref(12);
(3)操作数据
data1.value = 123;
2.3-reactive
作用:定义对象格式的响应式数据
如果用ref定义对象/数组,内部会自动将对象/数组转换为reactive代理器对象。
- const proxy=reactive(obj):接收一个普通对象然后返回该普通对象的响应式代理器对象。
- js中修改告诉不需要.value。
- 一般用来定义一个引用类型的响应数据。
2.4-toRefs
将响应式对象中所有属性包装为ref对象,并返回包含这些ref对象的普通对象。
应用:对trsctive定义的对象进行toRefs包装,包装之后的对象中每个属性都是响应式的。
2.5-响应式原理
通过proxy(代理):拦截对对象本身的操作,包括属性的读写、删除等操作。
通过Reflect(反射):动态对被代理对象的响应式属性进行特定的操作。
2.6-watch和watchEffect
watch - 指定监听数据:
- 监听指定的一个或多个响应式数据,一旦发生变化,就会自动执行监视回调。
- 如果是监听reactive对象中的属性,必须通过函数来指定。
- 监听多个数据,使用数组来指定。
- 默认初始时不指定回调,但是通弄过配置immediate为true,来指定初始时立即执行第一次。
- 通过配置deep为true,来指定深度监视。
watchEffect - 不指定监听数据:
- 不用直接指定啦监视的数据,回调函数中使用的哪些响应式数据就监听哪些响应式数据。
- 默认初始就会执行一次。
2.7-生命周期
vue2中的生命周期钩子函数依旧可以使用,不过建议使用vue3的钩子函数
2.8-ref获取元素
vue2中是用thisref.xxx来获取元素或组件,但是vue3中没有this的概念。
vue3通过ref创建响应式数据的api来获取元素。
1.使用ref创建响应式数据,假设叫x
2.模板中绑定ref属性,值为上面的x
注意不能使用v-bind动态绑定。
这是x就是一个dom元素或组件了。
2.9-自定义hook函数
hook函数翻译成中文就是钩子函数(注意并不是生命周期的钩子函数)
比如ref,reactive,computed,watch,onBeforeMount等都是hook函数,只不过他们都是vue内部hook函数。
1.创建一个函数,函数名称必须以"use"开头
2.函数必须return一些数据。
2.10-shallowReactive与shallowRef
他们都表示浅响应式。
- shallowReactive:只处理了对象第一层属性的响应式(值响应第一层)
- shallowRef:只有重新复制时才是响应式(不响应内部数据,只响应整体。)
2.11-readonly与shallowReadonly
- 他们表示只读代理对象
- readonly
- 深度只读
- 设置readonly后,修改响应式数据会报错。
- shalloReadonly
- 浅只读
- 设置shalloReadonly后,修改响应式数据的第一层数据会报错。
- 应用场景:
- 在某些特定情况下,我们可能不希望对数据进行更新的操作,那就可以包装成一个只读代理对象,而不能修改或删除。
2.12-toRaw与markRaw
- toRaw
- 返回reactive或readonly对象的原始数据
- 这是一个还原方法,可用于临时读取,得到的数据不具有响应式。
- markRow:
- 标记一个对象,使其不具有响应式
- 应用场景:
- 有些只不应被设置为响应式的,例如复杂的第三方实例或Vue组件对象。
- 当渲染具有不可变数据源的大列表时,跳过代理转换可以提高性能。
2.13-toRef
- 为响应式对象上的某个属性创建一个ref引用,更新是应用对象会同步更新。
- 与ref的区别:ref是拷贝了一份新的数据指单独操作,更新时相互不影响。
2.14-customRef
- 用于自定义一个ref,可以显示的控制依赖追踪和触发相应。
- 接受一个工厂函数,两个参数分别用于追踪的track与用于触发相应的trigger,并方法一个带有get和set属性的对象。
- 需求:使用customRef实现防抖函数
2.15-provide与inject
- provide和inject提供依赖注入,功能类似2.0的provide/inject
- 实现跨层级组件(祖孙)间通信。
2.16-响应式数据的判断
- isRef:检查一个值是否为一个ref对象。
- isReactive:检查一个对象是否否是由reactive对象的响应式代理。
- isReadonly:检查一个对象是否由readonly创建的只读代理。
- isProxy:检查一个对象是否是由reactive或者readonly方法创建的代理。
2.17-Fragment(片段)
- 在vue2中:组件中必须有一个跟标签
- 在vue3中:组价可以没有跟标签,内部会将多个标签包含在一个Fragment虚拟标签中。
- 好处:减少标签层级,减小内存占用
2.18-Teleport(瞬移)
- Teleport提供了一种干净的方法,让组件的html在父组件界面外的特定标签(很可能是body)下插入显示。
2.19-Suspense(不确定的)
Supense组件是配合一部组件使用的,它可以让一部组件返回数据前渲染一些后背内容。
那我们首先要学会一个异步组件。
- 在setup函数总返回一个promise,就是一个异步组件。
- setup函数携程async函数,也是一个异步组件。
2.20-其他新的API
-
全新的全局API:
- createApp()
- defineProperty()
- defineComponent()
- nextTick()
-
将原来的全局API转移到应用对象:
- app.component()
- app.config()
- app.directive()
- app.mount()
- app.umount()
- app.use()
2.21-useSlots和useAttrs
useSlots 和 useAttrs 是真实的运行时函数,它会返回与 setupContext.slots 和 setupContext.attrs 等价的值,同样也能在普通的组合式 API 中使用。
使用场景:父组件使用子组件的插槽
1.父组件
<template>
<h1>这是父组件</h1>
<p>插槽上面1</p>
<slots-attrs msg="我是props的msg" heihei="我是attr">
<template #header >
<div style="width:100%;height:100px;border:1px solid green;">我是父组件插槽--插入的内容。。。</div>
</template>
</slots-attrs>
<p>插槽下面2</p>
</template>
<script lang="ts" setup>
import SlotsAttrs from '@/components/04/SlotsAttrs.vue'
</script>
2.子组件
<template>
<Child ref="child"/>
{{msg}}
</template>
<script lang="ts" setup>
import { ref,onMounted } from 'vue';
import Child from '@/components/03/Child.vue'
const child = ref(null);
const msg=ref('')
onMounted(()=>{
console.log("进来了")
console.log(child.value.msg)
msg.value = child.value.msg;
})
</script>
三、路由
(1)userRout:获得当前路由对象。
(2)useRouter:获得路由实例,可以进行路由跳转。
import {useRoute,useRouter} from "vue-router"
四、Vue3+TS实战知识点
1.1-引入ElementPlus
(1)输入命令安装(全局引入)。
npm install element-plus --save
(2)【main.ts】文件中配置
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(ElementPlus)
1.2-引入axios
(1)输入命令安装。
npm install axios
(2)新建一个【http.ts】文件,写一个简单的请求封装。
//导入axios
import axios from "axios"
//axios.create创建一个axios实例
//我们给这个实例编写配置,后端所有通过这个实例发送请求,都受这个配置约束。
const $http=axios.create({
baseURL:"http://jsonplaceholder.typicode.com/",
timeout:1000
});
// 添加请求拦截器
$http.interceptors.request.use(function (config) {
// 在发送请求之前做些什么
return config;
}, function (error) {
// 对请求错误做些什么
return Promise.reject(error);
});
// 添加响应拦截器
$http.interceptors.response.use(function (response) {
// 对响应数据做点什么
return response.data;
}, function (error) {
// 对响应错误做点什么
return Promise.reject(error);
});
export default $http;
(3)新建一个【test.ts】文件进行二次封装。
import $http from "./http"
export const getData=$http.get("/posts");
(3)使用。
<script lang="ts">
import { defineComponent } from 'vue';
import {getData} from "@/apis/test"
export default defineComponent({
name: 'Home',
setup(){
//请求接口
getData.then((data:any)=>{
console.log(data);
})
return{
}
}
});
</script>
1.3-引入vuex
(1)输入命令安装vuex
npm install vuex
(2)在【main.ts】中引入。
import { createApp } from 'vue'
import App from './App.vue'
import store from './store'
createApp(App).use(store).mount('#app')
(3)在src文件夹下新建一个【store/index.ts】文件
import { createStore } from 'vuex'
import app from "./modules/app"
import settings from "./modules/settings"
import user from "./modules/user"
export default createStore({
// 导入模块
modules: {
app,
settings,
user
}
})
(4)【app.ts】格式如下。
//【应用程序模块】
const app={
//单一状态树,UI可通过this.$store.state.app.*获得数据
state: {
},
//对state数据进行过滤后返回(可以认为是 store 的计算属性)
getters:{
},
// 唯一拥有更改内存数据的接口,不可进行异步操作
mutations: {
},
// 与mutation通讯,UI层写入内存数据的接口,可异步操作
actions: {
}
}
export default app;
1.4-引入.env
(1)创建文件xxx.env文件。
----------------【.env.development】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = 'development'
# Base URL
BASE_URL = 'http://xxx:7881'
# Base API
VUE_APP_BASE_API = 'http://xxx:7881'
----------------【.env.production】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是production
NODE_ENV = 'production'
# Base URL
BASE_URL = 'http://xxx:7881'
# Base API
VUE_APP_BASE_API = 'http://xxx:7881'
----------------【.env.staging】---------------
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = 'development'
# Base URL
BASE_URL = 'http://xxx:7881'
# Base API
VUE_APP_BASE_API = 'http://xxx:7881'
(2)使用。
process.env.VUE_APP_BASE_API
1.5-引入cookie
(1)安装。
npm install vue-cookies --save
1.6-引入nprogress
(1)安装。
npm install nprogress -S
npm i @types/nprogress-D
(2) 现在我们对NProgress进行一下简单的封装,首先我们在【common/utils/nporgress.ts】目录下创建文件,然后引入NProgress和CSS样式文件 。
(3)内容如下。
import NProgress from 'nprogress' // 进度条
import 'nprogress/nprogress.css' // 进度条样
//全局进度条的配置
NProgress.configure({
easing: 'ease', // 动画方式
speed: 1000, // 递增进度条的速度
showSpinner: false, // 是否显示加载ico
trickleSpeed: 200, // 自动递增间隔
minimum: 0.3, // 更改启动时使用的最小百分比
parent: 'body', //指定进度条的父容器
})
//打开进度条
export const start =()=>{
NProgress.start();
}
//关闭进度条
export const close =()=>{
NProgress.done();
}
(4)在【router/index.ts】文件中使用
--引入文件
import { close, start } from '@/common/utils/nprogress'//进度条
--使用
const router = createRouter({
routes,
history: createWebHistory(),
})
router.beforeEach((pre, next) => {
start()
})
router.afterEach(() => {
close()
})
1.7-引入Element Plus(按需自动引入)
环境:
参考文献:https://www.yisu.com/zixun/723540.html
(1)输入命令安装
npm install element-plus
npm install -D unplugin-vue-components unplugin-auto-import
(2)在【vue.config.ts】中配置。
const AutoImport = require('unplugin-auto-import/webpack')
const Components = require('unplugin-vue-components/webpack')
const { ElementPlusResolver } = require('unplugin-vue-components/resolvers')
// 【每次修改,都需要重新build】
// 插件(module.exports={configureWebpack:[]})
plugins: [
AutoImport({
resolvers: [ElementPlusResolver()]
}),
Components({
resolvers: [ElementPlusResolver()]
})
],
(3)然后执行【npm run dev】报错了(如果报node-sass将这个卸载,安装sass即可)。
解决: 卸载nodev12,更新到nodev16在重新构建一下项目成功解决 了。
命令:
npm uninstall node-sass --dev-S
npm install sass --dev-S
1.8-引入sross-env环境变量配置
(1)安装。
npm i --save-dev cross-env
npm install dotenv-cli --dev-s
(2)创建文件。
--【.env.dev.build】
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = production
# Base URL
BASE_URL = 'http://xxx.xxx.xxx:7881'
# Base API
VUE_APP_BASE_API = 'http://xxx.xxx.xxx:7990'
# 统一认证中心配置
VUE_APP_AUTH_BASEURL = 'http://xxx.xxx.xxx:5021'
VUE_APP_AUTH_LOGIN_RRDIRECTURL = 'http://xxx.xxx.xxx:7881/callback'
VUE_APP_AUTH_LOGOUT_RRDIRECTURL = 'http://xxx.xxx.xxx:7881'
--【.env.dev.serve】
#以下的值webpack会根据不同的环境取得不同的值,使用方法:process.env.*
#设定一个标题,代表这个环境是development
NODE_ENV = development
# Base URL
BASE_URL = 'http://xxx.xxx.xxx:7881'
# Base API
VUE_APP_BASE_API = 'http://xxx.xxx.xxx:7990'
# 统一认证中心配置
VUE_APP_AUTH_BASEURL = 'http://xxx.xxx.xxx:5021'
VUE_APP_AUTH_LOGIN_RRDIRECTURL = 'http://localhost:7881/callback'
VUE_APP_AUTH_LOGOUT_RRDIRECTURL = 'http://localhost:7881'
(3) 【package.json】中的配置
"scripts": {
"dev": "npm run serve:dev",
"start": "npm run serve:dev",
"server": "npm run serve:dev",
"build": "npm run build:dev",
"serve:dev": "cross-env NODE_ENV=development dotenv -e .env.dev.serve vue-cli-service serve",
"build:dev": "cross-env NODE_ENV=production dotenv -e .env.dev.build vue-cli-service build",
"serve:test": "cross-env NODE_ENV=development dotenv -e .env.test.serve vue-cli-service serve",
"build:test": "cross-env NODE_ENV=production dotenv -e .env.test.build vue-cli-service build",
"serve:prod": "cross-env NODE_ENV=development dotenv -e .env.prod.serve vue-cli-service serve",
"build:prod": "cross-env NODE_ENV=production dotenv -e .env.prod.build vue-cli-service build",
"lint": "vue-cli-service lint"
},
1.9-引入js-cookie
(1)安装
npm install js-cookie -s
npm install @types/js-cookie --dev-s
(2)封装单独的ts文件。
import Cookies from 'js-cookie'
/*
封装操作Cookie本地存储的方法:
说明:主要用途有保存登录信息。
存储大小:4KB
*/
const cookies = {
/**
*设置Cookies
* @param {String} key 键
* @param {Object} value 值:存储的值可能是数组/对象,不能直接存储,需要转换 JSON.stringify()
* @param {Int} expiresTime 过期时间(单位:秒)
*/
set(key: string, value: any, expiresTime: number) {
expiresTime=arguments[2] ? arguments[2] : (60*60)*24;//默认值为:24小时
let expires = new Date(new Date().getTime() * 1 + expiresTime * 1000);
return Cookies.set(key, value, {
expires: expires
});
},
/**
* 获得Cookies
* @param {String} key 键
* @return {Object} 根据键取对应的值
*/
get(key: string) {
return Cookies.get(key);
},
/**
* 删除Cookies
* @param {String} key 键
*/
remove(key: string) {
return Cookies.remove(key);
}
};
export default cookies;
1.10-引入el-plus面包屑导航
(1)安装
npm install path-to-regexp -s
(2)写代码。
<template>
<el-breadcrumb class="app_breadcrumb" separator="/">
<transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in breadcrumbs" :key="item.path">
<span v-if="
item.path === ' ' ||
item.path === '/' ||
item.path === '-' ||
item.redirect === 'noredirect' ||
index == breadcrumbs.length - 1" class="no_redirect">
{{item.meta.title}}
</span>
<a v-else @click.prevent="handleLink(item)">{{item.meta.title}}</a>
</el-breadcrumb-item>
</transition-group>
</el-breadcrumb>
</template>
<script lang="ts" setup>
import { compile } from 'path-to-regexp'
import { useRouter, useRoute, RouteLocationMatched } from 'vue-router'
import { onBeforeMount, reactive, toRefs, watch } from 'vue'
const route = useRoute();
const router = useRouter();
const pathCompile = (path: string) => {
const { params } = route;
const toPath = compile(path);
return toPath(params);
}
const state = reactive({
// 面包屑路由
breadcrumbs: [] as Array<RouteLocationMatched>,
// 获得面包屑路由
getBreadcrumb: () => {
let matched = route.matched.filter((item: RouteLocationMatched) => {
return item.meta && item.meta.title;
});
const first = matched[0];
if (!state.isIndex(first)) {
matched = [{ path: '/index', meta: { title: '首页' } } as any].concat(matched);
}
state.breadcrumbs = matched.filter(
(item) => item.meta && item.meta.title
);
},
// 判断是不是首页
isIndex: (route: RouteLocationMatched):boolean => {
const name = route && route.name;
if (!name) {
return false;
}
return (
name.toString().trim().toLocaleLowerCase() === "Index".toLocaleLowerCase()
);
},
// 跳转路由
handleLink(item: any){
const { redirect, path } = item;
if (redirect) {
router.push(redirect).catch((err) => {
console.warn(err);
})
return
}
router.push(pathCompile(path)).catch((err) => {
console.warn(err);
})
}
});
// 加载
onBeforeMount(() => {
state.getBreadcrumb();
})
// 监听路由变化
watch(() => route.path, (path: string) => {
if (path.startsWith('/redirect/')) {
return;
}
state.getBreadcrumb();
})
const { breadcrumbs, handleLink } = toRefs(state);
</script>
<style lang="scss" scoped>
.app_breadcrumb.el-breadcrumb{
font-size: 14px;
line-height: 42px;
height:42px;
.el-breadcrumb__inner,
.el-breadcrumb__inner a {
font-weight: 400 !important;
}
.no_redirect{
color: #c0c4cc;
cursor: text;
}
}
</style>
(3)引入组件。
<breadcrumb class="breadcrumb_container" />
1.11-封装http请求【axios-mapper】
(1)安装需要的依赖
npm install @types/qs
npm install qs
(2)创建【types.ts】
// 请求内容类型
export enum ContentType {
form = 'application/x-www-form-urlencoded',
json = 'application/json; charset=utf-8',
multipart = 'multipart/form-data'
}
// 请求方式
export enum Method {
GET = 'GET',
POST = 'POST',
PUT = 'PUT',
PATCH = 'PATCH',
DELETE = 'DELETE'
}
// 网络请求参数
export interface RequestParams {
[key: string]: any
}
(3)创建【convert-model.ts】文件。
// Json-Model相互转换
export class ConvertModel {
/**
* @description: json转model
* @param {string} json
* @return {*}
*/
public static jsonToModel<T>(json: string): T {
return JSON.parse(json) as T;
}
/**
* @description: model转json
* @param {any} model
* @return {*}
*/
public static modelToJson(model: any): string {
return JSON.stringify(model);
}
}
(4)创建【index.ts】文件
import { RequestParams, Method, ContentType } from './types';
import axios, { AxiosInstance, AxiosRequestConfig } from 'axios';
import { ConvertModel } from './convert-model';
// 导出所有的类型
export * from './types';
export interface HttpClientConfig extends AxiosRequestConfig {
defaultParams?: RequestParams;
}
// 导出默认请求
export default class HttpClient {
private _defaultConfig: HttpClientConfig;
public httpClient: AxiosInstance;
// 构造函数
constructor(options: HttpClientConfig = {}){
this.httpClient = axios.create(options);
this._defaultConfig = options;
}
/**
* @description: 封装请求类
* @param {string} path 请求路径
* @param {Method} method 请求方式(默认:GET)
* @param {RequestParams} params 参数
* @param {ContentType} contentType http配置
* @param {HttpClientConfig} optionsSource
* @return {*}
*/
async request<T>(
path: string = '',
method: Method = Method.GET,
params?: RequestParams,
contentType: ContentType = ContentType.json,
optionsSource?: HttpClientConfig
):Promise<T> {
const options: any = Object.assign(
{},
this._defaultConfig,
optionsSource
);
const { headers } = options;
headers['content-type'] = contentType;
const allParams = Object.assign(
{},
this._defaultConfig.defaultParams,
params
);
// 发送请求
const requestConfig: HttpClientConfig = {
url: `${path}`,
method,
headers,
};
if(contentType === ContentType.form) {
requestConfig.params = allParams;
} else {
requestConfig.data = ConvertModel.modelToJson(allParams);
}
return this.httpClient.request(requestConfig)
.then(res => {
const data: string = ConvertModel.modelToJson(res.data);
if (res.status >= 200 && res.status < 300) {
return ConvertModel.jsonToModel(data) as T;
} else {
return Promise.reject(data);
}
})
.catch(async error => {
return Promise.reject(error);
})
};
// GET请求
get(url: string, params?: any) {
return this.httpClient.request({
url: url,
method: Method.GET,
params
});
};
// POST请求
post(url: string, data?: any) {
return this.httpClient.request({
url: url,
method: Method.POST,
data
});
};
// PUT请求
put(url: string, data?: any) {
return this.httpClient.request({
url: url,
method: Method.PUT,
data
});
};
// Delete请求
del (url: string, params?: any) {
return this.httpClient.request({
url: url,
method: Method.DELETE,
params
});
};
// Delete批量请求(Post方式传参)
del_batch(url: string, data?: any) {
return this.httpClient.request({
url: url,
method: Method.DELETE,
data
});
}
}
(5)使用,封装【https.ts】请求。
import HttpClient, { HttpClientConfig } from '../kimi-axios/index';
import { ElMessage } from 'element-plus';
import { getApiUrl, getToken } from './utils';
const config: HttpClientConfig = {
baseURL: getApiUrl(),
headers: {
'Content-Type': 'application/json;charset=utf-8'
},
timeout: 60 * 1000 // 请求超时时间(默认:60秒)
};
const https = new HttpClient(config);
// 请求拦截器
https.httpClient.interceptors.request.use(
config => {
// 在发送请求之前做些什么...
console.log('https:请求拦截器...');
// // 如果存在Token,让请求携带令牌。
// var curTime = new Date()
// var expiretime = new Date(Date.parse(storeTemp.state.user.tokenExpire))
// // 判断是否存在token,如果存在的话,则每个http header都加上token
// if (storeTemp.state.user.token && (curTime < expiretime && storeTemp.state.user.tokenExpire)) {
// //['Authorization']是一个自定义头密钥,请根据实际情况进行修改。
// config.headers['Authorization'] = 'Bearer ' + storeTemp.state.user.token;
// }
// ['Authorization']是一个自定义头密钥,请根据实际情况进行修改。
// config.headers['Authorization'] = 'Bearer ' + store.state.user.kimiToken;
config.headers = {
Authorization: `Bearer ${getToken()}`
};
return config;
},
error => {
// 处理请求错误...
return Promise.reject(error);
}
);
// 响应拦截器
https.httpClient.interceptors.response.use(
/**
* 如果您想获取http信息,如标题或状态
* 请返回response=>response
*/
/**
* 通过自定义代码确定请求状态
* 这里只是一个例子
* 您还可以通过HTTP状态代码来判断状态
*/
response => {
// 自定义错误
// if(!response.data.success){
// Message({
// message: response.data.error.message,
// type: 'error',
// duration: 2 * 1000
// })
// }
console.log('https:响应拦截器...');
const res = response;
return res;
},
error => {
let statusCode = 0;
try {
statusCode = error.response.status;
} catch (e) {
// 网络请求错误
if (error.toString().indexOf('Error: Network Error') !== -1) {
ElMessage({
message: '您的请求网络发生错误,请稍后重试!',
type: 'error',
duration: 2 * 1000
});
return Promise.reject(error);
}
}
// 超时请求处理
var originalRequest = error.config;
if (error.code === 'ECONNABORTED' && error.message.indexOf('timeout') !== -1 && !originalRequest._retry) {
ElMessage({
message: '您的请求超时,请稍后重试!',
type: 'error',
duration: 2 * 1000
});
originalRequest._retry = true;
return Promise.reject(error);
}
// 根据状态码处理
if (statusCode) {
if (statusCode === 401) {
// 401:未登录
ElMessage({
message: '您当前未登录,请先登录!',
type: 'error',
duration: 2 * 1000
});
} else if (statusCode === 403) {
// 403:无权限
ElMessage({
message: '您访问的权限等级不够,拒绝访问!',
type: 'error',
duration: 2 * 1000
});
} else if (statusCode === 429) {
// 429:IP限流
ElMessage({
message: '您刷新次数过多,请稍后重试!',
type: 'error',
duration: 2 * 1000
});
} else if (statusCode === 500) {
// 500:自动错误&&系统自定义错误
if (!error.response.data.success && error.response.data.result === 'error_constom') {
ElMessage({
message: error.response.data.error.message,
type: 'error',
duration: 2 * 1000
});
} else {
ElMessage({
message: '对不起,在处理您的请求期间,产生了一个服务器内部错误!',
type: 'error',
duration: 2 * 1000
});
}
} else {
// 其他
let errorMsg = '';
switch (statusCode) {
case 400:
errorMsg = '请求报文中存在语法错误!';
break;
case 404:
errorMsg = '服务器找不到请求的接口!';
break;
case 405:
errorMsg = '请求类型出错!';
break;
case 408:
errorMsg = '请求超时!';
break;
case 415:
errorMsg = '请重新登录!';
break;
case 501:
errorMsg = '服务未实现!';
break;
case 502:
errorMsg = '服务器作为网关或代理,从上游服务器收到无效响应!';
break;
case 503:
errorMsg = '服务不可用!';
break;
case 504:
errorMsg = '服务器连接超时!';
break;
case 505:
errorMsg = 'HTTP版本不受支持!';
break;
default:
errorMsg = '其他错误!';
}
ElMessage({
message: errorMsg,
type: 'error',
duration: 3 * 1000
});
}
} else {
ElMessage({
message: '您的接口请求失败,请稍后重试!',
type: 'error',
duration: 2 * 1000
});
}
return Promise.reject(error);
}
);
export default https;
1.12-引入全局loading
(1)element-plus需要在【main.ts】中先单独引入loading样式。
// 引入loading样式
import 'element-plus/theme-chalk/el-loading.css';
(2)新建【loading.ts】文件全局使用。
// 【全局 Loading】:以服务的方式调用的全屏 Loading 是单例的。
import { ElLoading } from 'element-plus'
export default function() {
const loading = (title: string) => {
const loadingInstance = ElLoading.service({
lock: true,
text: title,
background: 'rgba(0, 0, 0, 0.7)',
});
return loadingInstance;
};
return {
loading
}
}
(3)使用。文章来源:https://www.toymoban.com/news/detail-646911.html
// 导入
import Loading from '@/utils/loading';
//启用
const loadingInstance = loading('登录中...');
//关闭
loadingInstance.close();
原创地址:https://www.cnblogs.com/kimiliucn/p/17605624.html文章来源地址https://www.toymoban.com/news/detail-646911.html
到了这里,关于快速掌握Vue3:速成Vue3前端开发看这篇就够啦的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!