当前位置:   article > 正文

【无标题】vue封装侧边栏_vue侧边栏组件

vue侧边栏组件

Vue2

  1. <!-- 左侧导航组件 -->
  2. <!-- 使用说明:<side-bar></side-bar> -->
  3. <template>
  4. <div class="sidebar_wrap">
  5. <!-- <div class="wrap_title">
  6. <img src="@/assets/images/logo.png" alt />
  7. <div>张家湾数字管理平台</div>
  8. </div> -->
  9. <div class="wrap_catalog">
  10. <el-menu :default-active="'/'+NavActive" :unique-opened="isUnique" :router="isRouter" mode="vertical"
  11. ref="menu">
  12. <!-- 一级菜单 -->
  13. <template v-for="(item,index) in navData">
  14. <el-submenu v-if="item.children && item.children.length" :index="item.router" :key="index"
  15. ref="elMenu" class="list_one" @open="open">
  16. <template slot="title">
  17. <div @click="clickStatus($event,item)">
  18. <img :src="require('../assets/images/' +item.icon_none + '.png')" class="imgs1"
  19. v-if="item.status === '0'" />
  20. <span>{{item.name}}</span>
  21. </div>
  22. </template>
  23. <!-- 二级菜单 -->
  24. <template v-for="itemChild in item.children">
  25. <el-menu-item :index="itemChild.router" :key="itemChild.router">
  26. <span slot="title" class='submenu'>{{itemChild.name}}</span>
  27. </el-menu-item>
  28. </template>
  29. </el-submenu>
  30. <el-menu-item v-else :index="item.router" :key="item.router" @open="open" ref="elMenu"
  31. class="list_two">
  32. <div @click="clickStatus($event,item)">
  33. <img :src="require('../assets/images/' +item.icon_none + '.png')" class="imgs1"
  34. v-if="item.status === '0'" />
  35. <span slot="title">{{item.name}}</span>
  36. </div>
  37. </el-menu-item>
  38. </template>
  39. </el-menu>
  40. </div>
  41. </div>
  42. </template>
  43. <script>
  44. import {studentsList} from "../assets/js/studentsList";
  45. import {parentList} from '../assets/js/parentList'
  46. import {teacherList} from '../assets/js/teacherList'
  47. export default {
  48. name: "sidebar",
  49. data() {
  50. return {
  51. isUnique: true,
  52. isRouter: true,
  53. navData: [],
  54. NavActive: "",
  55. };
  56. },
  57. beforeMount() {
  58. this.getActiveNav();
  59. },
  60. watch: {
  61. //监听路由变化
  62. $route(index) {
  63. // console.log('sideBarRouter',index)
  64. let path = index.path.substr(1);
  65. this.handleSelect(path);
  66. },
  67. },
  68. created() {
  69. // this.navData = JSON.parse(localStorage.menus);
  70. },
  71. mounted() {
  72. let userVal = sessionStorage.getItem("userVal");
  73. if(userVal==0){
  74. this.navData = studentsList.list;
  75. this.$router.push({path:'/studentHome'})
  76. }else if(userVal==1){
  77. this.navData = parentList.list;
  78. this.$router.push({path:'/parentHome'})
  79. }else if(userVal==2){
  80. this.navData = teacherList.list
  81. this.$router.push({path:'/teacherHome'})
  82. }
  83. // console.log(sessionStorage.getItem("isGarden") === "0");
  84. // console.log(sessionStorage.getItem("isGarden") === "1");
  85. // // isGarden === 0 为园区端;isGarden === 1 为企业端
  86. // if (sessionStorage.getItem("isGarden") === "0") {
  87. // this.navData = navDataList.list;
  88. // } else if (sessionStorage.getItem("isGarden") === "1") {
  89. // this.navData = navdataa.list;
  90. // }
  91. },
  92. methods: {
  93. getActiveNav() {
  94. let currentUrl = window.location.href;
  95. this.NavActive = currentUrl.split("/").pop();
  96. },
  97. //监听路由的变化,对应菜单高亮显示
  98. handleSelect(index) {
  99. this.NavActive = index;
  100. },
  101. clickStatus(e, item) {
  102. // console.log(e,item)
  103. // console.log(this.$refs.elMenu)
  104. // this.$refs.elMenu.map((item1) => {
  105. // console.log(item1.$el)
  106. // // if(item1.active === false){
  107. // // }
  108. // })
  109. },
  110. open() {
  111. console.log("1");
  112. },
  113. },
  114. };
  115. </script>
  116. <style scoped lang="less">
  117. .sidebar_wrap {
  118. width: 1.4583rem;
  119. height: 100%;
  120. // background: #870000;
  121. background: #fff;
  122. overflow-y: auto;
  123. overflow-x: hidden;
  124. .wrap_title {
  125. display: flex;
  126. align-items: center;
  127. justify-content: center;
  128. font-size: 0.1111rem;
  129. color: #fff;
  130. height: 0.5556rem;
  131. img {
  132. width: 0.2778rem;
  133. height: 0.1528rem;
  134. margin-right: 0.0764rem;
  135. }
  136. }
  137. .wrap_catalog {
  138. /deep/ .el-menu {
  139. border-right: none;
  140. // background-color: #870000;
  141. background-color: #fff;
  142. width: 1.4583rem;
  143. li {
  144. padding: 0 !important;
  145. }
  146. .el-menu-item {
  147. height: 0.3056rem;
  148. line-height: 0.3056rem;
  149. font-size: 0.1111rem;
  150. color: #0E151E;
  151. // border-bottom: 0.0069rem solid #a43d3d;
  152. }
  153. .el-submenu__title {
  154. height: 0.3056rem;
  155. line-height: 0.3056rem;
  156. font-size: 0.1111rem;
  157. // color: #0E151E;
  158. // border-bottom: 0.0069rem solid #a43d3d;
  159. }
  160. .el-submenu__icon-arrow {
  161. display: none;
  162. }
  163. .el-menu-item.is-active {
  164. width: 1.4583rem;
  165. height: 0.3056rem;
  166. color: #FFFFFF;
  167. padding-left: 0.6944rem;
  168. // background: #B40024;
  169. // background: url("../assets/new_images/xuanzhong.png") no-repeat;
  170. background-color: #D9221A;
  171. // background-position: 0.0694rem 0.0486rem;
  172. }
  173. .el-menu-item:hover {
  174. // background: #B40024;
  175. background-color: #D9221A;
  176. color: #fff;
  177. // background: url("../assets/new_images/xuanzhong.png") no-repeat;
  178. // background-position: 0.0694rem 0.0486rem;
  179. }
  180. .el-submenu.is-active.is-opened {
  181. // background: #B40024;
  182. // background: url("../assets/new_images/xuanzhong.png") no-repeat;
  183. // background-position: 0.0694rem 0.0486rem;
  184. background-color: #D9221A;
  185. color: #fff;
  186. .el-menu-item.is-active {
  187. // background: #A20A1E;
  188. background-color: #D9221A;
  189. color: #fff;
  190. }
  191. .el-menu-item:hover {
  192. // background: #A20A1E;
  193. background-color: #D9221A;
  194. color: #fff;
  195. }
  196. }
  197. .el-submenu:hover {
  198. .el-menu-item:hover {
  199. // background: #A20A1E;
  200. background-color: #D9221A;
  201. color: #fff;
  202. }
  203. }
  204. .el-submenu__title:hover {
  205. // background: #B40024;
  206. // background: url("../assets/new_images/xuanzhong.png") no-repeat;
  207. // background-position: 0.0694rem 0.0486rem;
  208. background-color: #D9221A;
  209. color: #fff;
  210. .el-menu-item:hover {
  211. // background: #A20A1E;
  212. background-color: #D9221A;
  213. color: #fff;
  214. }
  215. }
  216. .el-submenu.is-opened:hover {
  217. // background: #B40024;
  218. // background: url("../assets/new_images/xuanzhong.png") no-repeat;
  219. // background-position: 0.0694rem 0.0486rem;
  220. background-color: #D9221A;
  221. color: #fff;
  222. .el-menu-item:hover {
  223. // background: #A20A1E;
  224. background-color: #D9221A;
  225. }
  226. }
  227. .imgs1 {
  228. width: 0.1389rem;
  229. height: 0.1389rem;
  230. margin-right: 0.0347rem;
  231. }
  232. .submenu {
  233. font-family: 'PingFang-Regular';
  234. }
  235. }
  236. .list_one:last-child {
  237. // border-bottom: 0.0069rem solid #870000;
  238. /deep/ .el-menu-item:last-child {
  239. // border-bottom: 0.0069rem solid #870000;
  240. }
  241. }
  242. .list_two:last-child {
  243. // border-bottom: 0.0069rem solid #870000;
  244. }
  245. }
  246. }
  247. </style>

以上是封装的侧边栏组件,需要搭配js文件使用,格式如下:

(px to rem 比例是144 需要使用px可以转回来)

  1. // 导航栏信息
  2. // 一级导航index要与其子代(二级)导航第一个index相同
  3. // name: 菜单要显示的名字
  4. // index: 导航地址(router中的名字)
  5. // img: 图标名字(用class定义)
  6. // children: 迭代子代导航、参数如上
  7. // 教师端
  8. export const teacherList = {
  9. "list": [
  10. {
  11. "name": "健康测评",
  12. "name_en": "teacherHome",
  13. "router": "/teacherHome",
  14. "icon_none": "shouyeIcon_255",
  15. "icon_block": "shouyeIcon_255",
  16. "status": '0',
  17. "children": [],
  18. },{
  19. "name": "心理测评",
  20. "name_en": "psychometrics",
  21. "router": "/psychometrics",
  22. "icon_none": "shouyeIcon_255",
  23. "icon_block": "shouyeIcon_255",
  24. "status": '0',
  25. "children": [],
  26. },{
  27. "name": "教学资源",
  28. "name_en": "teachResources",
  29. "router": "/teachResources",
  30. "icon_none": "shouyeIcon_255",
  31. "icon_block": "shouyeIcon_255",
  32. "status": '0',
  33. "children": [],
  34. },{
  35. "name": "在线研修",
  36. "name_en": "autonomouslyStudy",
  37. "router": "/autonomouslyStudy",
  38. "icon_none": "shouyeIcon_255",
  39. "icon_block": "shouyeIcon_255",
  40. "status": '0',
  41. "children": [
  42. {
  43. "name": "自主学习",
  44. "name_en": "autonomouslyStudy",
  45. "router": "/autonomouslyStudy",
  46. "icon_none": "shouyeIcon_255",
  47. "icon_block": "shouyeIcon_255",
  48. "status": '0',
  49. "children": [],
  50. },
  51. {
  52. "name": "教师调研",
  53. "name_en": "teacherResearch",
  54. "router": "/teacherResearch",
  55. "icon_none": "shouyeIcon_255",
  56. "icon_block": "shouyeIcon_255",
  57. "status": '0',
  58. "children": [],
  59. },
  60. {
  61. "name": "直播培训",
  62. "name_en": "liveTraining",
  63. "router": "/liveTraining",
  64. "icon_none": "shouyeIcon_255",
  65. "icon_block": "shouyeIcon_255",
  66. "status": '0',
  67. "children": [],
  68. },
  69. {
  70. "name": "在线阅读",
  71. "name_en": "onlineReading",
  72. "router": "/onlineReading",
  73. "icon_none": "shouyeIcon_255",
  74. "icon_block": "shouyeIcon_255",
  75. "status": '0',
  76. "children": [],
  77. },
  78. {
  79. "name": "课程研究",
  80. "name_en": "projectResearch",
  81. "router": "/projectResearch",
  82. "icon_none": "shouyeIcon_255",
  83. "icon_block": "shouyeIcon_255",
  84. "status": '0',
  85. "children": [],
  86. },
  87. {
  88. "name": "展示交流",
  89. "name_en": "displayCommunication",
  90. "router": "/displayCommunication",
  91. "icon_none": "shouyeIcon_255",
  92. "icon_block": "shouyeIcon_255",
  93. "status": '0',
  94. "children": [],
  95. },
  96. ],
  97. },
  98. ]
  99. }

Vue3 ====components===sidebar文件夹===sider.vue  sidebarItem.vue

sider.vue

  1. <script lang="ts" setup>
  2. // sidebarItem 项组件
  3. import SideBarItem from './sidebarItem.vue';
  4. import { useRouter } from 'vue-router';
  5. // 拿到路由列表,过滤我们不想要的
  6. const router = useRouter();
  7. const routerList = router.getRoutes().filter((v) => v.meta && v.meta.isShow);
  8. </script>
  9. <template>
  10. <div class="sidebar">
  11. <!-- 项目名称及logo -->
  12. <div class="sidebar-logo flex-center">
  13. <svg-icon icon-class="logo" />
  14. <span>VitalityAdmin</span>
  15. </div>
  16. <!-- 导航菜单 -->
  17. <el-menu
  18. active-text-color="#fff"
  19. background-color="#001529"
  20. :default-active="$route.path"
  21. text-color="#999"
  22. :unique-opened="true"
  23. router>
  24. <!-- 引入子组件 -->
  25. <SideBarItem :routerList="routerList" />
  26. </el-menu>
  27. <!-- active-text-color:当前菜单项被选中时,字体的颜色 -->
  28. <!-- background-color:这个menu菜单的背景色 -->
  29. <!-- default-active: 当前激活菜单的 index -->
  30. <!-- text-color:菜单项字体颜色 -->
  31. <!-- unique-opened:unique-opened 是否只保持一个子菜单的展开 -->
  32. <!-- router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 -->
  33. </div>
  34. </template>
  35. <style lang="scss" scoped>
  36. .sidebar {
  37. height: 100%;
  38. .sidebar-logo {
  39. height: 48px;
  40. background-color: #002140;
  41. color: #fff;
  42. font-weight: 700;
  43. line-height: 48px;
  44. text-align: center;
  45. font-size: 20px;
  46. }
  47. .el-menu {
  48. height: calc(100% - 48px);
  49. border-right: 0;
  50. overflow: auto;
  51. }
  52. }
  53. </style>

sidebarItem.vue

  1. <script setup lang="ts">
  2. import { RouteRecordRaw } from 'vue-router';
  3. // 做类型限制,解决ts类型报错
  4. type CustomRouteRecordRaw = RouteRecordRaw & {
  5. meta: {
  6. isShow?: boolean;
  7. };
  8. };
  9. const props = defineProps({
  10. // 拿到父组件传递过来的路由列表进行渲染
  11. routerList: {
  12. type: Array as () => CustomRouteRecordRaw[],
  13. required: true
  14. }
  15. });
  16. </script>
  17. <template>
  18. <template v-for="item in props.routerList" :key="item.path">
  19. <!-- 当该菜单项有子菜单时 -->
  20. <el-sub-menu :index="item.path" v-if="item.children && item.children.length > 0">
  21. <template #title v-if="item.meta.icon">
  22. <!-- 菜单项图标,我此处用的是全局封装的 svg组件 -->
  23. <el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
  24. <!-- 菜单项名称,在路由中定义好 -->
  25. <span>{{ item.meta.title }}</span>
  26. </template>
  27. <!-- 若路由中未定义菜单项icon,则仅展示名称--(我的仅一级菜单有图标) -->
  28. <template #title v-else>{{ item.meta.title }}</template>
  29. <!-- 递归遍历-自己调用自己(核心代码) -->
  30. <sidebarItem :routerList="( item.children as CustomRouteRecordRaw[])" />
  31. </el-sub-menu>
  32. <!-- 当前菜单项无子菜单 -->
  33. <el-menu-item :index="item.path" v-else>
  34. <!-- 与上面注释大致相同,不多做额外注释 -->
  35. <template v-if="item.meta.icon">
  36. <el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
  37. <span>{{ item.meta.title }}</span>
  38. </template>
  39. <template v-else>
  40. {{ item.meta.title }}
  41. </template>
  42. </el-menu-item>
  43. </template>
  44. </template>
  45. <style scoped lang="scss">
  46. .is-active {
  47. background: #409eff;
  48. font-weight: 700;
  49. }
  50. .el-menu-item {
  51. &:hover {
  52. color: #fff;
  53. font-weight: 700;
  54. }
  55. }
  56. .el-menu--collapse {
  57. .el-menu-item {
  58. justify-content: center;
  59. }
  60. }
  61. // 下列代码是用于兼容horizontal所写,酌情删或留
  62. .el-menu--horizontal {
  63. .el-menu-item.is-active {
  64. background-color: transparent !important;
  65. border-bottom: 2px solid #409eff !important;
  66. .el-icon,
  67. span {
  68. color: #409eff !important;
  69. }
  70. }
  71. .el-sub-menu.is-active {
  72. .el-sub-menu__title {
  73. border: 0 !important;
  74. }
  75. .el-icon,
  76. span {
  77. color: #409eff !important;
  78. }
  79. }
  80. }
  81. </style>

声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop】
推荐阅读
相关标签
  

闽ICP备14008679号