当前位置:   article > 正文

以element ui 的标签页与侧边导航联动的vue功能_element ui 标签页 导航栏 联动

element ui 标签页 导航栏 联动

侧栏与标签页的联动效果在后台管理中很常用,这个是以element ui为基础写的标签页与侧边导航联动的项目部分。

在整体布局layout页面中,测栏,其中最重要的两个参数default-active设为$router.path,则它会根据路由来激活样式,index设为遍历数组的url,跟路由地址一一匹配。

思路是遍历导航栏数组,在数组中有标题,图标,路由地址等信息,与路由信息相对应,点击每个导航项目时会将该条数组项目添加到store里,删除则反之。这主要是一级路由的列表,那么其他页面的标签我是通过监听路由,在里面包不包含,不包含就从当前的路由元信息里取。

layout.vue文件

  1. <template>
  2. <div class="layoutContent">
  3. <el-menu :default-active="$route.path" :router="true" active-text-color="#409eff" class="el-menu-vertical-demo"
  4. :class="{ showMenu: isCollapse }" mode="vertical">
  5. <!-- 因为要一直开着首页标签,所以我写死了 -->
  6. <el-menu-item @click="$router.push({ path: '/' })" index="/">
  7. <i class="el-icon-menu"></i>
  8. <span slot="title">首页</span>
  9. </el-menu-item>
  10. <el-menu-item v-for="(item, index) in list1" :key="item.title" :index="item.url"
  11. @select="menuSelect(index, indexPath)" @click="mainToPath(item)">
  12. <i :class="`el-icon-${item.icon}`"></i>
  13. <span slot="title">{{ item.title }}</span>
  14. </el-menu-item>
  15. </el-menu>
  16. <div class="layout">
  17. <div class="navbar">
  18. <i class="el-icon-s-unfold" @click="unfold"></i>
  19. <div class="user">
  20. <i class="el-icon-refresh" style="font-size: 20px" @click="refresh()"></i>
  21. <el-image style="width: 30px; height: 30px; border-radius: 50%"
  22. src="https://fuss10.elemecdn.com/e/5d/4a731a90594a4af544c0c25941171jpeg.jpeg"></el-image>
  23. <el-row class="block-col-2">
  24. <el-col :span="12">
  25. <el-dropdown trigger="click">
  26. <span class="el-dropdown-link">
  27. <i class="el-icon-arrow-down" style="font-size: 16px; margin-left: 10px"></i>
  28. </span>
  29. <el-dropdown-menu slot="dropdown">
  30. <el-dropdown-item v-for="(item, index) in list2" :icon="`el-icon-${item.icon}`"
  31. @click.native="setting(index)" :key="item.title">{{ item.title
  32. }}</el-dropdown-item>
  33. </el-dropdown-menu>
  34. </el-dropdown>
  35. </el-col>
  36. </el-row>
  37. </div>
  38. </div>
  39. <Head-Tag></Head-Tag>
  40. <el-dialog title="提示" :visible.sync="dialogVisible" width="90%">
  41. <span>确认退出吗</span>
  42. <span slot="footer" class="dialog-footer">
  43. <el-button @click="dialogVisible = false" size="mini">取 消</el-button>
  44. <el-button type="primary" size="mini" @click="dialogVisible = false">确 定</el-button>
  45. </span>
  46. </el-dialog>
  47. <router-view v-if="isRresh"></router-view>
  48. </div>
  49. </div>
  50. </template>
  51. <script>
  52. import { mapState, mapMutations } from "vuex";
  53. //tag组件
  54. import HeadTag from "@/components/headTag.vue";
  55. export default {
  56. components: {
  57. HeadTag,
  58. },
  59. data() {
  60. return {
  61. isCollapse: false,
  62. isRresh: true,
  63. dialogVisible: false,
  64. index: "",
  65. list1: [
  66. { title: "", icon: "menu", url: "/***" },
  67. { title: "", icon: "document", url: "/***" },
  68. { title: "", icon: "setting", url: "" },
  69. ],
  70. };
  71. },
  72. watch: {
  73. ["$route.path"]: function (newVal, olderVal) {
  74. if (newVal === "/") return;
  75. if (newVal === "/editUser")
  76. this.$route.meta.title = JSON.parse(
  77. window.sessionStorage.getItem("title")
  78. ).title;
  79. for (let j = 0; j < this.list1.length; j++) {
  80. // 若上面列表里没有包含当前的路由信息,则从当前路由元信息里取
  81. if (newVal && !this.list1[j].url.includes(newVal)) {
  82. this.$store.commit("mutationSelectTags", this.$route.meta);
  83. }
  84. }
  85. },
  86. ["$store.state.stateTagsList"]: function (newVal, olderVal) {
  87. // 若tag中的数据条为0,就跳转到首页
  88. if (newVal.length === 0) {
  89. this.$router.push({ path: "/" }).catch((err) => { });
  90. }
  91. },
  92. },
  93. methods: {
  94. mainToPath(value) {
  95. // 一级主跳转并选择tag
  96. this.$store.commit("mutationSelectTags", value);
  97. this.$router.push({ path: value.url }).catch((err) => { });
  98. },
  99. unfold() {
  100. // 侧栏开关
  101. this.isCollapse = !this.isCollapse;
  102. },
  103. ...mapState({ state: "state" }),
  104. ...mapMutations({
  105. closeAll: "mutationCloseAllTag",
  106. }),
  107. setting(index) {
  108. //设置小功能,可有可无
  109. if (index === 0) {
  110. // 关闭全部tag
  111. this.closeAll();
  112. }
  113. if (index === 1) {
  114. if (this.$router.history.current.path === "/") {
  115. this.$message("您已在首页了!");
  116. return;
  117. }
  118. this.$router.push({ path: "/" }).catch((err) => { });
  119. }
  120. if (index === 2) this.dialogVisible = true;
  121. },
  122. },
  123. };
  124. </script>
  125. <style>
  126. .el-tabs__content {
  127. display: none;
  128. }
  129. </style>
  130. <style lang="scss" scoped>
  131. .el-menu-item {
  132. padding-left: 1vh !important;
  133. }
  134. .layoutContent {
  135. display: flex;
  136. .el-menu-vertical-demo {
  137. width: 0px;
  138. overflow: hidden;
  139. transition: all 0.3s;
  140. }
  141. .showMenu {
  142. width: 118px;
  143. }
  144. }
  145. .layout {
  146. background-color: rgb(247, 248, 250);
  147. height: 100vh;
  148. width: 70%;
  149. // flex-shrink: 1;
  150. flex-grow: 1;
  151. .tabs {
  152. background-color: white;
  153. margin-top: 2px;
  154. }
  155. .navbar {
  156. display: flex;
  157. justify-content: space-between;
  158. align-items: center;
  159. width: 100%;
  160. height: 50px;
  161. background-color: white;
  162. font-size: 25px;
  163. padding: 0 20px;
  164. box-sizing: border-box;
  165. }
  166. .user {
  167. display: flex;
  168. align-items: center;
  169. }
  170. .el-icon-refresh {
  171. margin-right: 10px;
  172. }
  173. }
  174. .el-dropdown-link {
  175. cursor: pointer;
  176. color: #409eff;
  177. }
  178. .el-icon-arrow-down {
  179. font-size: 12px;
  180. }
  181. .demonstration {
  182. display: block;
  183. color: #8492a6;
  184. font-size: 14px;
  185. margin-bottom: 20px;
  186. }
  187. ::v-deep .el-tabs {
  188. background-color: #fff;
  189. }
  190. ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item {
  191. background-color: #fff;
  192. border-radius: 0px 0px 10px 10px !important;
  193. }
  194. ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__nav,
  195. ::v-deep .el-tabs--card>.el-tabs__header {
  196. border: none !important;
  197. background-color: #eaf4fe !important;
  198. }
  199. ::v-deep .el-tabs--card>.el-tabs__header .el-tabs__item.is-active {
  200. border: none !important;
  201. border-radius: 10px 10px 0px 0px !important;
  202. background: transparent !important;
  203. }
  204. </style>

tags.vue文件

  1. <template>
  2. <div class="app-tag">
  3. <el-tag size="medium" :disable-transitions="true" :effect="$route.path === '/' ? 'dark' : 'plain'" :hit="true"
  4. @click="$router.push({ path: '/' })">
  5. <i class="el-icon-custom"></i>
  6. 首页
  7. </el-tag>
  8. <el-tag closable size="medium" v-for="(tag, index) in tags" :key="index" :disable-transitions="true"
  9. :effect="$route.path === tag.url ? 'dark' : 'plain'" :hit="true" @close="handleClose(tag, index)"
  10. @click="handleClick(tag)">
  11. <i :class="`el-icon-${tag.icon}`"></i>
  12. {{ tag.title }}
  13. </el-tag>
  14. </div>
  15. </template>
  16. <script>
  17. import { mapState, mapMutations } from 'vuex';
  18. export default {
  19. data() {
  20. return {
  21. tags: [],
  22. }
  23. },
  24. created() {
  25. //stateTagsList的值默认为空数组
  26. this.tags = this.stateTagsList;
  27. },
  28. computed: {
  29. ...mapState(['stateTagsList'])
  30. },
  31. mounted() {
  32. // 返回时删除二级tags目录
  33. let _this = this
  34. window.addEventListener("popstate", function (e) {
  35. _this.closeCurrent()
  36. }, false);
  37. },
  38. methods: {
  39. ...mapMutations({
  40. close: 'mutationCloseTag',
  41. closeCurrent: 'mutationCloseCurrentTag'
  42. }),
  43. handleClose(tag, index) {
  44. this.close(tag) // 删除当前tag
  45. if (this.$router.path === tag?.url) { // 如果关闭的标签不是当前路由的话,不做路由跳转
  46. return
  47. } else {
  48. if (index === (this.tags.length - 1)) { // 关闭最后一个标签,则路由跳转至最后一个
  49. this.$router.push({ path: this.tags[index]?.url })
  50. } else { // 路由跳转至下一个标签页
  51. if (index === 0) {
  52. this.$router.push({ path: this.tags[0]?.url })
  53. } else {
  54. this.$router.push({ path: this.tags[index - 1]?.url })
  55. }
  56. }
  57. }
  58. },
  59. // 点击tags具体标签
  60. handleClick(tag) {
  61. this.$router.push({ path: tag?.url }).catch(err => { })
  62. }
  63. }
  64. }
  65. </script>
  66. <style lang="scss" scoped>
  67. .app-tag {
  68. padding: 0 10px;
  69. margin-bottom: 1vh;
  70. display: flex;
  71. align-items: center;
  72. flex-wrap: nowrap;
  73. overflow-x: scroll;
  74. padding-bottom: 4px;
  75. .el-tag {
  76. cursor: pointer;
  77. border: 0;
  78. border-radius: 0 0 10px 10px;
  79. background-color: #fff;
  80. color: black;
  81. ::v-deep .el-tag__close {
  82. color: black;
  83. }
  84. }
  85. .el-tag--dark {
  86. border-radius: 0;
  87. background-color: #eaf4fe;
  88. color: #409eff;
  89. ::v-deep .el-tag__close {
  90. color: #409eff;
  91. }
  92. }
  93. }</style>

store文件

  1. import Vue from "vue";
  2. import Vuex from "vuex";
  3. Vue.use(Vuex);
  4. export default new Vuex.Store({
  5. state: {
  6. stateTagsList: [],
  7. },
  8. getters: {},
  9. mutations: {
  10. mutationSelectTags(state, data) {
  11. // 选择tag标签
  12. let result = false;
  13. for (let i = 0; i < state.stateTagsList.length; i++) {
  14. if (state.stateTagsList[i].url === data.url) {
  15. return (result = true);
  16. }
  17. }
  18. result === false ? state.stateTagsList.push(data) : "";
  19. },
  20. mutationCloseTag(state, data, _router) {
  21. // 单击关闭tag标签
  22. let result = state.stateTagsList.findIndex(
  23. (item) => item.url === data.url
  24. );
  25. state.stateTagsList.splice(result, 1);
  26. },
  27. mutationCloseAllTag(state, data) {
  28. // 关闭全部tag
  29. state.stateTagsList.splice(0, state.stateTagsList.length);
  30. },
  31. mutationCloseCurrentTag(state, data) {
  32. // 返回时关闭一个tag
  33. state.stateTagsList.splice(-1, 1);
  34. },
  35. },
  36. actions: {},
  37. modules: {},
  38. });

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/530533
推荐阅读
相关标签
  

闽ICP备14008679号