一、被动退出
主要实现功能:进行时间比较,判断是否过期
在src下创建一个utils文件夹,再在其下创建auth.js和constant.js(用于存放常量值)
//constant.js
export const TOKEN_TIME='tokenTime'
//定时器中1000就是一秒钟 下面就是两小时
export const TOKEN_TIME_VALUE=60*1000*60*2
// auth.js
// 引入常量
import { TOKEN_TIME, TOKEN_TIME_VALUE } from './constant'
// 登陆时设置时间
export const setTokenTime = () => {
localStorage.setItem(TOKEN_TIME, Date.now())
}
// 获取登陆时间
export const getTokenTime = () => {
return localStorage.getItem(TOKEN_TIME)
}
// 比较,查看是否已经过期
export const diffTokenTime = () => {
const currentTime = Date.now() // 当前时间
const tokenTime = getTokenTime() // 登陆时间
return (currentTime - tokenTime) > TOKEN_TIME_VALUE
}
在之前定义的拦截器中进行判断
//request.js
service.interceptors.request.use(config=>{
if (localStorage.getItem('token')){
if(diffTokenTime()){
store.dispatch('app/logout')
return Promise.reject(new Error('token失效'))
}
}
config.headers.Authorization=localStorage.getItem('token')
return config
首先判断是否存在token,如果存在则判断之前定义的diffTokenTime,如果时间过期,则退出并引发error
再去store/module/app.js中在action定义logout函数
// 退出
logout({commit}){
commit('setToken','')
localStorage.clear()
router.replace('/login')
}
并在登录时定义登录时间
import {setTokenTime} from '@/utils/auth'
login({ commit }, userInfo) {
return new Promise((resolve, reject) => {
loginApi(userInfo)
.then((res) => {
console.log(res)
commit('setToken', res.token)
setTokenTime()
router.replace('/')
resolve()
})
.catch((err) => {
reject(err)
})
})
},
// 退出
logout({ commit }) {
commit('setToken', '')
localStorage.clear()
router.replace('/login')
二、汉堡按钮伸缩项
1.首先在layout下创建header文件夹,再创建index.vue
<template>
<div class="navbar">
</div>
</template>
<script setup>
</script>
<style lang="scss" scoped>
.navbar {
width: 100%;
height: 60px;
overflow: hidden;
background-color: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
padding: 0 16px;
display: flex;
align-items: center;
box-sizing: border-box;
position: relative;
.navbar-right {
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
::v-deep .navbar-item {
display: inline-block;
margin-left: 18px;
font-size: 22px;
color: #5a5e66;
box-sizing: border-box;
cursor: pointer;
}
}
}
</style>
2.再去layout下的index.vue中定义。asideWidth 用来消除边框距离
import Headers from './headers'
import { ref } from 'vue'
const asideWidth = ref(210)
<el-aside :width="asideWidth + 'px'" class="sidebar-container">
<Menu />
</el-aside>
<el-container class="container">
<el-header><Headers /></el-header>
再去headers下创建components文件夹,再创建hamburger.vue
<template>
<div class="hamburger-conatiner">
<svg-icon icon="hamburger-opened"></svg-icon>
</div>
</template>
<script setup></script>
<style lang="scss" scoped>
.hamburger-conatiner {
margin-right: 16px;
box-sizing: border-box;
cursor: pointer;
}
</style>
再去headers下进行注册
<template>
<div class="navbar">
<hamburger></hamburger>
</div>
</template>
<script setup>
import hamburger from './components/hamburger.vue'
</script>
在store/app.js中进行状态的配置
import { login as loginApi} from '@/api/login'
import router from '@/router'
import {setTokenTime} from '@/utils/auth'
export default{
namespaced: true,
state:()=>({
token:localStorage.getItem('token') || '',
// 操控边栏的切换
siderType:true
}),
mutations:{
setToken(state,token){
state.token=token
localStorage.setItem('token',token)
},
//切换边栏状态函数
changeSiderType(state){
state.siderType=!state.siderType
}
},
actions:{
login({ commit }, userInfo) {
return new Promise((resolve, reject) => {
loginApi(userInfo)
.then((res) => {
console.log(res)
commit('setToken', res.token)
setTokenTime()
router.replace('/')
resolve()
})
.catch((err) => {
reject(err)
})
})
},
// 退出
logout({ commit }) {
commit('setToken', '')
localStorage.clear()
router.replace('/login')
}
}
}
在hambarger.vue中进行定义
<script setup>
import { useStore } from 'vuex';
const store=useStore()
const toggleClick=()=>{
store.commit('app/changeSiderType')
}
</script>
为了可以动态的切换图标,则在store/getters进行定义
siderType:state=>state.app.siderType
再回到hambarger.vue中,将icon绑定数据
<svg-icon :icon="icon"></svg-icon>
判断当前的siderType ,进行图标的切换
<script setup>
import { useStore } from 'vuex'
import { computed } from 'vue'
const store = useStore()
const toggleClick = () => {
store.commit('app/changeSiderType')
}
const icon = computed(() => {
return store.getters.siderType ? 'hamburger-opened' : 'hamburger-closed'
})
</script>
2.在menus中添加伸缩项,到element-plus官网找到menu的属性中的水平折叠collapse
:collapse="!$store.getters.siderType"
3.当折叠时,应让边栏变窄;再次点击图标,边栏再次回复正常
import { computed } from 'vue'
import { useStore } from 'vuex'
// const asideWidth = ref(210)
const store = useStore()
const asideWidth = computed(() => {
return store.getters.siderType ? '210' : '70'
})
使用计算属性实现
<el-container
class="container"
:class="{ hidderContainer: !$store.getters.siderType }"
>
三、实现动态面包屑导航
1.到element-plus官网
2.在headers/component下创建breadcrumb.vue
<template>
<el-breadcrumb separator="/">
<el-breadcrumb-item>promotion detail</el-breadcrumb-item>
</el-breadcrumb>
3.到headers下的index.vue中
import breadcrumb from './components/breadcrumb.vue'
<breadcrumb></breadcrumb>
4.再回到breadcrumb.vue中:
//引入useRoute
import { useRoute } from 'vue-router'
//在setup中声明并使用
const route = useRoute()
console.log(route.matched)
useRouter:是全局路由实例
useRoute:当前激活的路由的状态信息,包含了当前 URL 解析得到的信息,还有 URL 匹配到的 route路由记录
route.matched返回路由表
<template>
<el-breadcrumb separator="/">
<el-breadcrumb-item v-for="(item, index) in breadcrumbList" :key="index"
><span class="no-redirect" v-if="index === breadcrumbList[-1]">{{
item.name
}}</span>
<span class="redirect" v-else @click="handleRedirect(item.path)">{{
item.name
}}</span>
</el-breadcrumb-item>
</el-breadcrumb>
</template>
<script setup>
import { watch, ref } from 'vue'
import { useRoute, useRouter } from 'vue-router'
const route = useRoute()
const router = useRouter()
console.log(route.matched)
const breadcrumbList = ref([])
const initBreadcrumbList = () => {
breadcrumbList.value = route.matched
console.log(route.matched)
}
watch(
route,
() => {
initBreadcrumbList()
},
{ deep: true, immediate: true }
)
const handleRedirect = (path) => {
router.push(path)
}
</script>
<style lang="scss" scoped>
.no-redirect {
color: #97a8be;
cursor: text;
}
.redirect {
color: #666;
font-weight: 600;
cursor: pointer;
&:hover {
color: $menuBg;
}
}
</style>