vue实战:第三部分

一、被动退出

主要实现功能:进行时间比较,判断是否过期
在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>

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值