使用vue3.2实现多页签导航
作者:前端er小芳
这篇文章主要为大家详细介绍了如何使用vue3.2 + elementPlus + pinia 实现多页签导航,文中的示例代码讲解详细,有需要的小伙伴可以参考一下
一、实现思路
- 单击菜单时数据添加store对象,添加数据时要去重以及数量限制,不可无限添加
- 多页签导航数据从store对象里取
- 初始化会显示【首页】标签导航,同时固定不可删除
- 单击多页签导航,跳转到对应路由
- 激活样式处理
- 持久化处理
- 删除多页签导航事件
二、具体实现步骤
1. 定义store
// src/store/tag-list.js import { defineStore } from "pinia"; export const useTagStore = defineStore('tag',{ state: ()=> ({ tagList: [ // 初始化默认展示【首页】标签导航 { path:'/index', name: 'index', meta: { title: '首页'} } ] }), getters: { tagListGetter: state=> state.tagList }, actions: { addTag(item) { this.tagList.push(item) }, delTag(item) { // 找出要删除的tag的索引值 const i = this.tagList.findIndex(v => v.path === item.path) this.tagList.splice(i,1) } }, // 持久化 persist: { enabled: true, // 开启 strategies: [ { key: 'tagList', storage: sessionStorage } ] }
2. 单击菜单时数据添加store对象
在导航组件中(naveItem.vue)添加点击事件addTag
<!-- 无子级 --> <el-menu-item :index="item.path" v-if="!item.children" @click="addTag(item)"> <el-icon><Menu /></el-icon> <span>{{item.meta.title}}</span> </el-menu-item> <!-- 有子级 --> <el-sub-menu :index="item.path" v-else> <template #title>{{item.meta.title}}</template> <nav-item v-for="sub in item.children" :key="sub.path" :item="sub"></nav-item> </el-sub-menu>
addTag方法逻辑如下,已有注释,不再详细说明。
import { storeToRefs } from 'pinia' import { useTagStore } from '@/store/tag-list.js' const tagStore = useTagStore() const { tagList } = storeToRefs(tagStore) const { item } = defineProps({ item: { type: Object } }) // 点击路由,添加标签导航,注意去重 const addTag = (item) => { // 添加前判断是否已存在 const isRepeat = tagList.value.some(v => v.path === item.path) // 找到则返回true,否则返回false if(isRepeat) return // 限制最多只能打开10个标签导航页 if(tagList.value.length === 10) { // 自动把第二个删除 tagStore.delTag(tagList.value[1]) } // 添加 tagStore.addTag(item) }
3. 定义一个tag组件
定义一个tag组件,从store中取出tagList并渲染;
1.首页标签导航不可关闭,通过当前tag的path不等于首页的path来控制el-tag的closeable是否展示;
2.定义默认展示的导航标签defaultUrl,默认为首页的path(/index);通过监听路由变化,将defaultUrl 等于变化后的路由地址;并且在template中判断:tag的path是否等于defaultUrl,是则不设置type(el-tag不设置type默认为蓝色),其他则为type=info;
3.点击导航标签,能够跳转到对应路由,给标签添加handleJump事件。
4.删除导航标签事件
a.删除的不是当前激活模块,正常删除
b.删除的是当前激活模块
- 当前激活模块是最后一个导航标签,则需要高亮前一个导航标签
- 当前激活模块不是最后一个导航标签,则需要高亮后一个导航标签
代码代码如下:
<div class="tags"> <el-scrollbar class="scroll-container"> <el-tag v-for="(tag,index) in tagList" :key="tag.path" class="mx-1" :closable="tag.path !== '/index'" :type="tag.path === defaultUrl? '' : 'info'" @click="handleJump(tag)" @close="handleClose(tag,index)" > {{ tag?.meta?.title }} </el-tag> </el-scrollbar> </div>
import { ref,watch } from 'vue' import { useRoute, useRouter } from 'vue-router' import { storeToRefs } from 'pinia' import { useTagStore } from '@/store/tag-list.js' const route = useRoute() const router = useRouter() const tagStore = useTagStore() const { tagList } = storeToRefs(tagStore) // 高亮当前路由导航的标签页 const defaultUrl = ref('/idnex') watch(route,(newVal,oldVal) => { defaultUrl.value = newVal.path },{deep: true,immediate: true}) // 跳转路由 const handleJump = (tag) => { // 重复点击标签,不跳转 if(route.path === tag.path) return router.push(tag.path) } // 关闭标签 const handleClose = (tag, i) => { // store 删除 tagStore.delTag(tag) // 1.删除非当前模块,正常删除 if(route.path !== tag.path) return // 2.删除当前模块 if(i === tagList.value.length) { // 2.1当前模块属于最后一个模块,删除后需要高亮前一个模块 handleJump(tagList.value[i-1]) }else { // 2.2当前模块属于中间模块模块,删除后需要高亮后一个模块 handleJump(tagList.value[i]) } }
具体效果
到此这篇关于使用vue3.2实现多页签导航的文章就介绍到这了,更多相关vue多页签导航内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!