效果
2-1 store里添加logout action
退出登录时 调用user/logout action 清空store token tags view 刷新跳转到登录页 这里退出登录接口我就不写了
src/store/modules/user.ts
import { Module, MutationTree, ActionTree } from 'vuex'
import { IRootState } from '@/store'
import { login } from '@/api/user'
import { setToken, removeToken } from '@/utils/auth'
// login params
export interface IUserInfo {
username: string;
password: string;
}
// 定义state类型
export interface IUserState {
token: string;
}
// mutations类型
type IMutations = MutationTree<IUserState>
// actions类型
type IActions = ActionTree<IUserState, IRootState>
// 定义state
const state: IUserState = {
token: ''
}
// 定义mutation
const mutations: IMutations = {
SET_TOKEN(state, token: string) {
state.token = token
}
}
// 定义action
const actions: IActions = {
login({ commit }, userInfo: IUserInfo) {
const { username, password } = userInfo
return new Promise((resolve, reject) => {
login({ username: username.trim(), password }).then(response => {
const { data } = response
console.log('data', data)
commit('SET_TOKEN', data.token)
setToken(data.token) // localStorage中保存token
resolve(data)
}).catch(error => {
reject(error)
})
})
},
logout({ commit, dispatch }) {
// 退出登录接口我这里就不写了
return new Promise<void>((resolve) => {
// 清空store里token
commit('SET_TOKEN', '')
// 清空localStorage里的token
removeToken()
// 清除所有tag views 派发的是全局action 需要 root: true
dispatch('tagsView/delAllViews', null, { root: true })
resolve()
})
}
}
// 定义user module
const user: Module<IUserState, IRootState> = {
namespaced: true,
state,
mutations,
actions
}
export default user
2-2 退出登录
src/layout/components/avatar/index.vue
<template>
<el-dropdown
class="avatar-container">
<div class="avatar-wrapper">
<img :src="avatar" class="user-avatar">
<i class="el-icon-caret-bottom" />
</div>
<template #dropdown>
<el-dropdown-menu>
<router-link to="/">
<el-dropdown-item>首页</el-dropdown-item>
</router-link>
<router-link to="/profile/index">
<el-dropdown-item>个人设置</el-dropdown-item>
</router-link>
<el-dropdown-item divided @click="logout">
<span style="display: block">退出登录</span>
</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</template>
<script lang="ts">
import avatar from '@/assets/logo.png'
import { defineComponent, getCurrentInstance } from 'vue'
import { useStore } from '@/store'
export default defineComponent({
setup() {
const store = useStore()
const { proxy } = getCurrentInstance()!
const logout = () => {
store.dispatch('user/logout').then(() => {
proxy?.$message.success('退出登录')
window.location.reload()
})
}
return {
logout,
avatar
}
}
})
</script>
<style lang="scss" scoped>
.avatar-container {
margin-right: 30px;
.avatar-wrapper {
margin-top: 5px;
.user-avatar {
width: 40px;
height: 40px;
border-radius: 10px;
cursor: pointer;
}
.el-icon-caret-bottom {
cursor: pointer;
font-size: 12px;
}
}
}
</style>
本节参考源码
https://gitee.com/brolly/vue3-element-admin/commit/9bc1a8f83c299d2bb1c7884b03f077bfde930592