vue3写了一个路由标签导航栏组件
时间:2023-8-3 19:19 作者:小诸葛 分类: Vue 正在检查是否收录...
vue3里面引入就可以使用,vue2需要注册一下在调用。
大致思路,进入页面的时候监听路由,判断当前路由的地址,然后把这个地址用来做激活样式匹配,接下来就是点击事件,点击谁就把激活样式给谁,其次是删除如果删除的是第一个,下次跳转默认下标为0的标签,并且附带激活样式,如果不是就跳转上一个也是index+1。这里面用了一点ts语法!
<LabelNav />
<script lang="ts" setup>
import LabelNav from '../components/LabelNav.vue'
</script>
效果展示:
完整代码
<template>
<div class="DynamicMenu">
<el-scrollbar>
<div class="scrollbar-flex-content">
<div @click="switching(item.to)" :class="{ 'DynamicMenu-span': true, 'active': item.to == path }"
v-for="(item, index) in label " :key="index">
<span>{{ item.title }}</span>
<span @click="removeTag(index); $event.stopPropagation()" class="ax"></span>
</div>
</div>
</el-scrollbar>
</div>
</template>
<script setup lang="ts">
import { reactive, watch, ref } from 'vue';
import { useRoute, useRouter } from 'vue-router';
let $route = useRoute()
let $router = useRouter()
interface LabelItem {
title: string;
to: string;
}
let path = ref()
let label = reactive<LabelItem[]>([
])
path.value = $route.path
// 页面加载的时候读取本地tab标签
const storedTabs = localStorage.getItem('tab');
if (storedTabs) {
const newTabs = JSON.parse(storedTabs) as LabelItem[];
newTabs.forEach(newTab => {
const hasDuplicate = label.some(item => item.title === newTab.title);
if (!hasDuplicate) {
label.push(newTab);
}
});
} else {
label.push({ title: '后台首页', to: '/index' })
localStorage.setItem('tab', JSON.stringify(label))
}
// 监听路由变化,进行激活样式更改和标签存储
watch(() => $route.meta.title, (newTitle) => {
path.value = $route.path//激活样式
let tis: string = newTitle as string;
// 检查是否存在相同的项,存储标签
const hasDuplicate = label.some(item => item.title === tis);
if (!hasDuplicate) {
label.push({ title: tis, to: $route.path });
localStorage.setItem('tab', JSON.stringify(label))
}
});
// 删除标签
let removeTag = (index: number) => {
if (label.length === 1) {
return;
} else {
label.splice(index, 1);
// 如果删除的是第一个标签,则跳转下一个,反之则跳转上一个
if (index === 0) {
path.value = label[0].to;
$router.push(label[0].to);
} else {
path.value = label[index - 1].to;
$router.push(label[index - 1].to);
}
localStorage.setItem('tab', JSON.stringify(label));
}
}
// 点击标签跳转
let switching = (to: string) => {
path.value = to
$router.push(to)
}
</script>
<style lang="scss" scoped>
.DynamicMenu {
width: 100%;
height: 30px;
background-color: #f5f7fa;
position: relative;
top: 0;
display: flex;
align-items: center;
.DynamicMenu-span {
height: 25px;
min-width: 100px;
background-color: #35a2ef;
display: flex;
align-items: center;
justify-content: center;
margin: 0 2px;
padding: 0 10px;
font-size: 12px;
color: #fff;
position: relative;
span {
height: 100%;
line-height: 25px;
}
}
.ax {
width: 20px;
height: 20px;
position: relative;
position: absolute;
right: 0;
}
.DynamicMenu-span .ax::after,
.DynamicMenu-span .ax::before {
content: "";
width: 2px;
height: 10px;
top: 6px;
border-radius: 50%;
background-color: #fff;
right: 10px;
position: absolute;
transition: transform 0.3s ease;
}
.DynamicMenu-span .ax::after {
transform: rotate(-45deg);
}
.DynamicMenu-span .ax::before {
transform: rotate(45deg);
}
.DynamicMenu-span .ax:hover::after {
transform: rotate(45deg);
background-color: #ff0000;
}
.DynamicMenu-span .ax:hover::before {
transform: rotate(-45deg);
background-color: #ff0000;
}
.active {
background-color: white;
color: #35a2ef;
border: 1px solid #35a2ef;
}
}
.scrollbar-flex-content {
display: flex;
}
.scrollbar-demo-item {
flex-shrink: 0;
display: flex;
align-items: center;
justify-content: center;
width: 100px;
height: 50px;
margin: 10px;
text-align: center;
border-radius: 4px;
background: var(--el-color-danger-light-9);
color: var(--el-color-danger);
}
</style>
推荐阅读:
扫描二维码,在手机上阅读