赞
踩
侧栏与标签页的联动效果在后台管理中很常用,这个是以element ui为基础写的标签页与侧边导航联动的项目部分。
在整体布局layout页面中,测栏,其中最重要的两个参数default-active设为$router.path,则它会根据路由来激活样式,index设为遍历数组的url,跟路由地址一一匹配。
思路是遍历导航栏数组,在数组中有标题,图标,路由地址等信息,与路由信息相对应,点击每个导航项目时会将该条数组项目添加到store里,删除则反之。这主要是一级路由的列表,那么其他页面的标签我是通过监听路由,在里面包不包含,不包含就从当前的路由元信息里取。
layout.vue文件
- <template>
- <div class="layoutContent">
- <el-menu :default-active="$route.path" :router="true" active-text-color="#409eff" class="el-menu-vertical-demo"
- :class="{ showMenu: isCollapse }" mode="vertical">
- <!-- 因为要一直开着首页标签,所以我写死了 -->
- <el-menu-item @click="$router.push({ path: '/' })" index="/">
- <i class="el-icon-menu"></i>
- <span slot="title">首页</span>
- </el-menu-item>
- <el-menu-item v-for="(item, index) in list1" :key="item.title" :index="item.url"
- @select="menuSelect(index, indexPath)" @click="mainToPath(item)">
- <i :class="`el-icon-${item.icon}`"></i>
- <span slot="title">{{ item.title }}</span>
- </el-menu-item>
- </el-menu>
- <div class="layout">
- <div class="navbar">
- <i class="el-icon-s-unfold" @click="unfold"></i>
- <div class="user">
- <i class="el-icon-refresh" style="font-size: 20px" @click="refresh()"></i>
- <el-image style="width: 30px; height: 30px; border-radius: 50%"
- src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-image>
-
- <el-row class="block-col-2">
- <el-col :span="12">
- <el-dropdown trigger="click">
- <span class="el-dropdown-link">
- <i class="el-icon-arrow-down" style="font-size: 16px; margin-left: 10px"></i>
- </span>
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item v-for="(item, index) in list2" :icon="`el-icon-${item.icon}`"
- @click.native="setting(index)" :key="item.title">{{ item.title
- }}</el-dropdown-item>
- </el-dropdown-menu>
- </el-dropdown>
- </el-col>
- </el-row>
- </div>
- </div>
- <Head-Tag></Head-Tag>
- <el-dialog title="提示" :visible.sync="dialogVisible" width="90%">
- <span>确认退出吗</span>
- <span slot="footer" class="dialog-footer">
- <el-button @click="dialogVisible = false" size="mini">取 消</el-button>
- <el-button type="primary" size="mini" @click="dialogVisible = false">确 定</el-button>
- </span>
- </el-dialog>
- <router-view v-if="isRresh"></router-view>
- </div>
- </div>
- </template>
- <script>
- import { mapState, mapMutations } from "vuex";
- //tag组件
- import HeadTag from "@/components/headTag.vue";
- export default {
- components: {
- HeadTag,
- },
- data() {
- return {
- isCollapse: false,
- isRresh: true,
- dialogVisible: false,
- index: "",
- list1: [
- { title: "", icon: "menu", url: "/***" },
- { title: "", icon: "document", url: "/***" },
- { title: "", icon: "setting", url: "" },
- ],
- };
- },
-
- watch: {
- ["$route.path"]: function (newVal, olderVal) {
- if (newVal === "/") return;
- if (newVal === "/editUser")
- this.$route.meta.title = JSON.parse(
- window.sessionStorage.getItem("title")
- ).title;
- for (let j = 0; j < this.list1.length; j++) {
- // 若上面列表里没有包含当前的路由信息,则从当前路由元信息里取
- if (newVal && !this.list1[j].url.includes(newVal)) {
- this.$store.commit("mutationSelectTags", this.$route.meta);
- }
- }
- },
- ["$store.state.stateTagsList"]: function (newVal, olderVal) {
- // 若tag中的数据条为0,就跳转到首页
- if (newVal.length === 0) {
- this.$router.push({ path: "/" }).catch((err) => { });
- }
- },
- },
-
- methods: {
- mainToPath(value) {
- // 一级主跳转并选择tag
- this.$store.commit("mutationSelectTags", value);
- this.$router.push({ path: value.url }).catch((err) => { });
- },
- unfold() {
- // 侧栏开关
- this.isCollapse = !this.isCollapse;
- },
- ...mapState({ state: "state" }),
- ...mapMutations({
- closeAll: "mutationCloseAllTag",
- }),
- setting(index) {
- //设置小功能,可有可无
- if (index === 0) {
- // 关闭全部tag
- this.closeAll();
- }
- if (index === 1) {
- if (this.$router.history.current.path === "/") {
- this.$message("您已在首页了!");
- return;
- }
- this.$router.push({ path: "/" }).catch((err) => { });
- }
- if (index === 2) this.dialogVisible = true;
- },
- },
- };
- </script>
-
- <style>
- .el-tabs__content {
- display: none;
- }
- </style>
- <style lang="scss" scoped>
- .el-menu-item {
- padding-left: 1vh !important;
- }
-
- .layoutContent {
- display: flex;
-
- .el-menu-vertical-demo {
- width: 0px;
- overflow: hidden;
- transition: all 0.3s;
- }
-
- .showMenu {
- width: 118px;
- }
- }
-
- .layout {
- background-color: rgb(247, 248, 250);
- height: 100vh;
- width: 70%;
- // flex-shrink: 1;
- flex-grow: 1;
-
- .tabs {
- background-color: white;
- margin-top: 2px;
- }
-
- .navbar {
- display: flex;
- justify-content: space-between;
- align-items: center;
- width: 100%;
- height: 50px;
- background-color: white;
- font-size: 25px;
- padding: 0 20px;
- box-sizing: border-box;
- }
-
- .user {
- display: flex;
- align-items: center;
- }
-
- .el-icon-refresh {
- margin-right: 10px;
- }
- }
-
- .el-dropdown-link {
- cursor: pointer;
- color: #409eff;
- }
-
- .el-icon-arrow-down {
- font-size: 12px;
- }
-
- .demonstration {
- display: block;
- color: #8492a6;
- font-size: 14px;
- margin-bottom: 20px;
- }
-
- ::v-deep .el-tabs {
- background-color: #fff;
- }
-
- ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item {
- background-color: #fff;
- border-radius: 0px 0px 10px 10px !important;
- }
-
- ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__nav,
- ::v-deep .el-tabs--card>.el-tabs__header {
- border: none !important;
- background-color: #eaf4fe !important;
- }
-
- ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
- border: none !important;
- border-radius: 10px 10px 0px 0px !important;
- background: transparent !important;
- }
- </style>
tags.vue文件
- <template>
- <div class="app-tag">
- <el-tag size="medium" :disable-transitions="true" :effect="$route.path === '/' ? 'dark' : 'plain'" :hit="true"
- @click="$router.push({ path: '/' })">
- <i class="el-icon-custom"></i>
- 首页
- </el-tag>
- <el-tag closable size="medium" v-for="(tag, index) in tags" :key="index" :disable-transitions="true"
- :effect="$route.path === tag.url ? 'dark' : 'plain'" :hit="true" @close="handleClose(tag, index)"
- @click="handleClick(tag)">
- <i :class="`el-icon-${tag.icon}`"></i>
- {{ tag.title }}
- </el-tag>
- </div>
- </template>
- <script>
- import { mapState, mapMutations } from 'vuex';
- export default {
- data() {
- return {
- tags: [],
- }
- },
- created() {
- //stateTagsList的值默认为空数组
- this.tags = this.stateTagsList;
- },
- computed: {
- ...mapState(['stateTagsList'])
- },
- mounted() {
- // 返回时删除二级tags目录
- let _this = this
- window.addEventListener("popstate", function (e) {
- _this.closeCurrent()
- }, false);
- },
- methods: {
- ...mapMutations({
- close: 'mutationCloseTag',
- closeCurrent: 'mutationCloseCurrentTag'
- }),
- handleClose(tag, index) {
- this.close(tag) // 删除当前tag
- if (this.$router.path === tag?.url) { // 如果关闭的标签不是当前路由的话,不做路由跳转
- return
- } else {
- if (index === (this.tags.length - 1)) { // 关闭最后一个标签,则路由跳转至最后一个
- this.$router.push({ path: this.tags[index]?.url })
- } else { // 路由跳转至下一个标签页
- if (index === 0) {
- this.$router.push({ path: this.tags[0]?.url })
- } else {
- this.$router.push({ path: this.tags[index - 1]?.url })
- }
- }
- }
- },
- // 点击tags具体标签
- handleClick(tag) {
- this.$router.push({ path: tag?.url }).catch(err => { })
- }
- }
- }
- </script>
- <style lang="scss" scoped>
- .app-tag {
- padding: 0 10px;
- margin-bottom: 1vh;
- display: flex;
- align-items: center;
- flex-wrap: nowrap;
- overflow-x: scroll;
- padding-bottom: 4px;
-
- .el-tag {
- cursor: pointer;
- border: 0;
- border-radius: 0 0 10px 10px;
- background-color: #fff;
- color: black;
-
- ::v-deep .el-tag__close {
- color: black;
- }
- }
-
- .el-tag--dark {
- border-radius: 0;
- background-color: #eaf4fe;
- color: #409eff;
-
- ::v-deep .el-tag__close {
- color: #409eff;
- }
- }
- }</style>
store文件
- import Vue from "vue";
- import Vuex from "vuex";
- Vue.use(Vuex);
- export default new Vuex.Store({
- state: {
- stateTagsList: [],
- },
- getters: {},
- mutations: {
- mutationSelectTags(state, data) {
- // 选择tag标签
- let result = false;
- for (let i = 0; i < state.stateTagsList.length; i++) {
- if (state.stateTagsList[i].url === data.url) {
- return (result = true);
- }
- }
- result === false ? state.stateTagsList.push(data) : "";
- },
- mutationCloseTag(state, data, _router) {
- // 单击关闭tag标签
- let result = state.stateTagsList.findIndex(
- (item) => item.url === data.url
- );
- state.stateTagsList.splice(result, 1);
- },
- mutationCloseAllTag(state, data) {
- // 关闭全部tag
- state.stateTagsList.splice(0, state.stateTagsList.length);
- },
- mutationCloseCurrentTag(state, data) {
- // 返回时关闭一个tag
- state.stateTagsList.splice(-1, 1);
- },
- },
- actions: {},
- modules: {},
- });
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。