0


【前端】Vue+Element UI案例:通用后台管理系统-面包屑、tag栏

文章目录

参考视频:
VUE项目,VUE项目实战,vue后台管理系统,前端面试,前端面试项目
案例链接【前端】Vue+Element UI案例:通用后台管理系统-导航栏(视频p1-16)https://blog.csdn.net/karshey/article/details/127640658【前端】Vue+Element UI案例:通用后台管理系统-Header+导航栏折叠(p17-19)https://blog.csdn.net/karshey/article/details/127652862【前端】Vue+Element UI案例:通用后台管理系统-Home组件:卡片、表格(p20-22)https://blog.csdn.net/karshey/article/details/127674643【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表准备:axios封装、mock数据模拟实战(p23-25)https://blog.csdn.net/karshey/article/details/127735159【前端】Vue+Element UI案例:通用后台管理系统-Echarts图表:折线图、柱状图、饼状图(p27-30)https://blog.csdn.net/karshey/article/details/127737979【前端】Vue+Element UI案例:通用后台管理系统-面包屑、tag栏(p31-35)https://blog.csdn.net/karshey/article/details/127756733【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Form表单填写、Dialog对话框弹出(p36-38)https://blog.csdn.net/karshey/article/details/127787418【前端】Vue+Element UI案例:通用后台管理系统-用户管理:Table表格增删查改、Pagination分页、搜索框(p39-42)https://blog.csdn.net/karshey/article/details/127777962【前端】Vue+Element UI案例:通用后台管理系统-登陆页面Login(p44)https://blog.csdn.net/karshey/article/details/127795302【前端】Vue+Element UI案例:通用后台管理系统-登陆页面功能:登录权限跳转、路由守卫、退出(p45-46)https://blog.csdn.net/karshey/article/details/127849502【前端】Vue+Element UI案例:通用后台管理系统-登陆不同用户显示不同菜单、动态添加路由(p47-48)https://blog.csdn.net/karshey/article/details/127865621【前端】Vue+Element UI案例:通用后台管理系统-项目总结https://blog.csdn.net/karshey/article/details/127867638

目标

在这里插入图片描述

  • 点击左边的tab栏,如果在面包屑上没有则添加
  • 点击面包屑或tag可以进行路由跳转
  • tag可以删除
  • 若删除的是当前页面,则路由跳转至下一个tag
  • 若删除的当前页面是最后一个,则跳转至前一个
  • 用vuex完成组件间的通信

代码

0.创建组件、完成路由

首先,我们并没有Mall、User等组件,我们要先创建它们,然后写到路由上。至于有哪些路由,见数据

MenuData

const MenuData=[{path:'/',name:'home',label:'首页',icon:'s-home',url:'Home/Home'},{path:'/mall',name:'mall',label:'商品管理',icon:'video-play',url:'MallManage/MallManage'},{path:'/user',name:'user',label:'用户管理',icon:'user',url:'UserManage/UserManage'},{label:'其他',icon:'location',children:[{path:'/page1',name:'page1',label:'页面1',icon:'setting',url:'Other/PageOne'},{path:'/page2',name:'page2',label:'页面2',icon:'setting',url:'Other/PageTwo'}]}]exportdefault MenuData

则router下的index.js如下:

import Vue from"vue";import VueRouter from"vue-router";import Main from'../Views/Main'import Home from'../Views/Home.vue'import Mall from'../Views/Mall.vue'import User from'../Views/User.vue'import PageOne from'../Views/PageOne.vue'import PageTwo from'../Views/PageTwo.vue'
Vue.use(VueRouter)const routes=[// 主路由{path:'/',component:Main,redirect:'/home',// 重定向children:[// 子路由// 这是本次写的部分{path:'/home',name:'home',component: Home },// 首页{path:'/user',name:'user',component: User },// 用户管理{path:'/mall',name:'mall',component: Mall },// 商品管理{path:'/page1',name:'page1',component: PageOne },// 页面1{path:'/page2',name:'page2',component: PageTwo },// 页面2]}]const router =newVueRouter({
    routes
})exportdefault router

1.面包屑

面包屑是放在Header的。我们打开Element UI,找到对应的组件:
在这里插入图片描述

<el-breadcrumbseparator="/"><el-breadcrumb-item:to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item><ahref="/">活动管理</a></el-breadcrumb-item><el-breadcrumb-item>活动列表</el-breadcrumb-item><el-breadcrumb-item>活动详情</el-breadcrumb-item></el-breadcrumb>

写进CommonHeader中:

<divclass="l-content"><el-button@click="handleMenu"icon="el-icon-menu"size="mini"></el-button><!-- 面包屑 --><el-breadcrumbseparator="/"><el-breadcrumb-item:to="{ path: '/' }">首页</el-breadcrumb-item></el-breadcrumb></div>

我们这里要动态绑定路由的数据,点了某个路由才会显示它。

注意:首页是不管怎样都会有的,因此首页的路由数据是写死在vuex的store的state中的,而其他的是动态添加的(Array.push)

2.用Vuex完成数据的通信:从Aside和Header到面包屑和tag

为什么会有组件间数据的通信呢?因为我们点击路由跳转在Aside,显示的面包屑在Header,而tag在每一个组件都要显示,所以它要单独写一个组件放进Main中。

而组件间的通信我们用的是Vuex,这个在之前用过,具体不再赘述。

在store文件夹下的tab.js添加:

  • tagList:在state中,用于表示面包屑的数据
  • selectMenu:在mutation中,用于更新面包屑的数据
exportdefault{state:{isCollapse:false,//导航栏是否折叠tabList:[{path:'/',name:'home',label:'首页',icon:'s-home',url:'Home/Home'}],//面包屑的数据:点了哪个路由,首页是一定有的},mutations:{// 修改导航栏展开和收起的方法CollapseMenu(state){
            state.isCollapse =!state.isCollapse
        },// 更新面包屑的数据SelectMenu(state, item){// 如果点击的不在面包屑数据中,则添加const index = state.tabList.findIndex(val=> val.name === item.name)if(index ===-1){
                state.tabList.push(item)}}}}

要在Aside的侧边栏点击事件处添加面包屑部分代码:

clickItem(item){// 防止自己跳自己的报错if(this.$route.path !== item.path &&!(this.$route.path ==='/home'&&(item.path ==='/'))){this.$router.push(item.path)}// 面包屑this.$store.commit('SelectMenu',item)}

到这里,只要在侧边栏点击了tab,就会产生路由跳转,且点击的数据若是新产生的,则会添加到tagList中。加粗部分是我们上面代码所完成的需求。

接下来我们需要将tagList中的数据在面包屑中显示出来。在Header的面包屑部分绑定数据:v-for对每一个tagList:

<!-- 面包屑 --><el-breadcrumbseparator="/"><el-breadcrumb-itemv-for="item in tags":key="item.path":to="{ path: item.path }">
    {{item.label}}
    </el-breadcrumb-item></el-breadcrumb>

js:

mapState 

是辅助函数,不了解的话可以去看vuex官方文档。由于本篇目的只在于做项目,函数功能不赘述。

import{ mapState }from'vuex'exportdefault{computed:{...mapState({tags:state=> state.tab.tabList
        })}}

效果:从上到下把所有tab都点一遍。显然完成了需求,但是样式不对。
在这里插入图片描述

3.面包屑样式

面包屑样式需求:

  • 和button同一行
  • 上下居中
  • 和左边button有距离
  • 最后一个的字是白色(#fff)
  • 其他颜色的字是灰色(#666)

css:

.l-content{display: flex;
    // 上下居中
    align-items: center;.el-breadcrumb{margin-left: 15px;// deep 强制生效
        /deep/.el-breadcrumb__item{.el-breadcrumb__inner{&.is-link{color: #666;}}&:last-child{.el-breadcrumb__inner{color: #fff;}}}}}

效果:
在这里插入图片描述

4.tag栏结构

tag栏在任何页面都要出现,说明它要单独写成一个组件CommonTags.vue,并放在Main中。

在这里插入图片描述
在Element UI中找到tag组件:
在这里插入图片描述

稍微看一下script代码,很明显我们用不到它。

<el-tagv-for="tag in tags":key="tag.name"closable:type="tag.type">
  {{tag.name}}
</el-tag>

代码中不了解的属性(Attributes)可以在文档中查一下。红框中为本次会用到的属性:
在这里插入图片描述

<template><divclass="tabs"><!-- closable是否可删除:除了"首页"都可删 --><!-- effect:主题,当前主题是dark,其他事plain --><el-tagv-for="item in tags":key="item.path":closable="item.name !== 'home'":effect="item.name === $route.name ? 'dark' : 'plain'">
            {{ item.label }}
        </el-tag></div></template><script>import{ mapState }from'vuex'exportdefault{computed:{...mapState({tags:state=> state.tab.tabList
        })}}</script><style></style>

5.tag事件

  • 删除:点击x删除对应的tag和面包屑
  • 若删除的是当前页面,则路由跳转至下一个tag
  • 若删除的当前页面是最后一个,则跳转至前一个
  • 点击:点击哪个tag就跳转到哪个tag

这两个事件分别为:(第一万次感叹,组件真好用)
在这里插入图片描述
html:

<el-tagv-for="(item, index) in tags":key="item.path":closable="item.name !== 'home'":effect="item.name === $route.name ? 'dark' : 'plain'"@click="changeMenu(item)"@close="handleClose(item, index)">
    {{ item.label }}
</el-tag>

点击事件:

changeMenu(item){this.$router.push({name: item.name })}

删除事件:

handleClose(item, index){// 删除面包屑数据this.$store.commit('closeTag', item)// 如果删除的刚好是自己if(item.name ===this.$route.name){const length =this.tags.length
        // 如果删除的是最后一个:跳到前一个if(length === index){this.$router.push({name:this.tags[index -1].name })}// 不是最后一个:往后一个else{this.$router.push({name:this.tags[index].name })}}}

store中的tab.js,在mutation里:

// 删除tag:删除tabList中对应的itemcloseTag(state, item){// 要删除的是state.tabList中的itemconst index = state.tabList.findIndex(val=> val.name === item.name)
    state.tabList.splice(index,1)}

6.tag样式

.tabs{padding: 20px;.el-tag{margin-right: 15px;
        // 鼠标悬停:小手
        cursor: pointer;}}

效果

在这里插入图片描述

总代码

本篇修改或新建的文件

在这里插入图片描述

CommonTags.vue

<template><divclass="tabs"><!-- closable是否可删除:除了"首页"都可删 --><!-- effect:主题,当前主题是dark,其他事plain --><el-tagv-for="(item, index) in tags":key="item.path":closable="item.name !== 'home'":effect="item.name === $route.name ? 'dark' : 'plain'"@click="changeMenu(item)"@close="handleClose(item, index)">
            {{ item.label }}
        </el-tag></div></template><script>import{ mapState }from'vuex'exportdefault{methods:{changeMenu(item){this.$router.push({name: item.name })},handleClose(item, index){// 删除面包屑数据this.$store.commit('closeTag', item)// 如果删除的刚好是自己if(item.name ===this.$route.name){const length =this.tags.length
                // 如果删除的是最后一个:跳到前一个if(length === index){this.$router.push({name:this.tags[index -1].name })}// 不是最后一个:往后一个else{this.$router.push({name:this.tags[index].name })}}}},computed:{...mapState({tags:state=> state.tab.tabList
        })}}</script><stylelang="less"scoped>.tabs{padding: 20px;.el-tag{margin-right: 15px;
        // 鼠标悬停:小手
        cursor: pointer;}}</style>

tab.js

exportdefault{state:{isCollapse:false,//导航栏是否折叠tabList:[{path:'/',name:'home',label:'首页',icon:'s-home',url:'Home/Home'}],//面包屑的数据:点了哪个路由,首页是一定有的},mutations:{// 修改导航栏展开和收起的方法CollapseMenu(state){
            state.isCollapse =!state.isCollapse
        },// 更新面包屑的数据SelectMenu(state, item){// 如果点击的不在面包屑数据中,则添加const index = state.tabList.findIndex(val=> val.name === item.name)if(index ===-1){
                state.tabList.push(item)}},// 删除tag:删除tabList中对应的itemcloseTag(state, item){// 要删除的是state.tabList中的itemconst index = state.tabList.findIndex(val=> val.name === item.name)
            state.tabList.splice(index,1)}}}

router的index.js

import Vue from"vue";import VueRouter from"vue-router";import Main from'../Views/Main'import Home from'../Views/Home.vue'import Mall from'../Views/Mall.vue'import User from'../Views/User.vue'import PageOne from'../Views/PageOne.vue'import PageTwo from'../Views/PageTwo.vue'
Vue.use(VueRouter)const routes=[// 主路由{path:'/',component:Main,redirect:'/home',// 重定向children:[// 子路由{path:'/home',name:'home',component: Home },// 首页{path:'/user',name:'user',component: User },// 用户管理{path:'/mall',name:'mall',component: Mall },// 商品管理{path:'/page1',name:'page1',component: PageOne },// 页面1{path:'/page2',name:'page2',component: PageTwo },// 页面2]}]const router =newVueRouter({
    routes
})exportdefault router
标签: vue.js 前端 ui

本文转载自: https://blog.csdn.net/karshey/article/details/127756733
版权归原作者 karshey 所有, 如有侵权,请联系我们删除。

“【前端】Vue+Element UI案例:通用后台管理系统-面包屑、tag栏”的评论:

还没有评论