Vue3.x使用Element Plus组件登录过期多次弹窗问题
一、问题
-
Vue3.x
版本配合使用Element Plus
组件库,当前用户登录过期时,出现多次弹窗,效果如下图所示:
-
出现的原因,后端进行身份过期的判断,当过期时请求接口参数
code!==200
,前端响应拦截时做了统一错误抛出处理;
二、解决
-
解决方法分为两种:
-
第一种(与
Vue
2.x版本问题类似):这种方式适用于在响应拦截时统一进行了抛错提示处理,利用一个状态值进行限制,当code!==200
时在响应拦截处对响应数据进行拦截处理,保证一次弹窗,代码如下:// 响应拦截,补充在自己的响应拦截函数中 import { ElMessage } from 'element-plus' ... // 设置状态值,用于控制弹窗提示 let status = true; axios.interceptors.response.use(res => { if (res.data.code && res.data.code != 200 && status) { if (res.data.code == 1500 || res.data.code == 401) { sessionStorage.clear() router.push({ path: "/login" }) } status = false; ElMessage({ type: "error", message: res.data.msg }) let timeout = setTimeout(() => { status = true; clearTimeout(timeout); }, 1500) } return res })
-
第二种,这种方式适用于在每个接口都单独进行了抛错处理提示,利用
Element Plus
组件库中ElMessage
组件新增属性appendTo
,appendTo
属性说明如下,通过设置组件的根元素,将弹窗的父组件设置在当前界面最外层元素身上,而不是默认值body
上面,以此达到跳转至登录界面时不会出现弹窗的问题,在响应拦截中只需要对过期状态进行拦截并抛出错误提示即可,这样就只会弹出一条提示,并且这种方式灵活性相较第一种灵活性更高:
属性 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
appendTo | 设置组件的根元素 | string /HTMLElement | - | document.body |
// 响应拦截,补充在自己的响应拦截函数中
import { ElMessage } from 'element-plus'
...
axios.interceptors.response.use(res => {
if (res.data.code && res.data.code == 1500 || res.data.code == 401) {
sessionStorage.clear()
router.push({
path: "/login"
})
ElMessage({
type: "error",
message: res.data.msg
})
}
return res
})
// 列表详情界面arsenalList.vue
<template>
<div class="arsenal-list" id="arsenal-list">
...
</div>
</template>
// 其它界面使用ElMessage
...
// 请求api
<script setup>
import { ElMessage } from 'element-plus'
import { arsenalListApi } from '@/api/arsenal.js'
...
// 列表数据
const list = ref([])
...
const getData = () => {
const res = await arsenalListApi(id)
// 接口处单独做了提示处理
if (res.code !== 200) {
// 先判断根元素是否存在,如果为undefined组件会默认添加到body元素上
if (document.getElementById('arsenal-list')) {
// 利用appendTo属性将弹窗选择在当前界面最外层添加
ElMessage({
appendTo: document.getElementById('arsenal-list'),
message: res.msg,
type: 'error',
})
return
}
}
list.value = res.data
}
...
</script>
到这里问题就解决了,如果有更好的方法欢迎补充讨论!🌈