【无标题】vue封装侧边栏

Vue2

<!-- 左侧导航组件 -->
<!-- 使用说明:<side-bar></side-bar> -->
<template>
	<div class="sidebar_wrap">
		<!-- <div class="wrap_title">
      <img src="@/assets/images/logo.png" alt />
      <div>张家湾数字管理平台</div>
    </div> -->
		<div class="wrap_catalog">
			<el-menu :default-active="'/'+NavActive" :unique-opened="isUnique" :router="isRouter" mode="vertical"
				ref="menu">
				<!-- 一级菜单 -->
				<template v-for="(item,index) in navData">
					<el-submenu v-if="item.children && item.children.length" :index="item.router" :key="index"
						ref="elMenu" class="list_one" @open="open">
						<template slot="title">
							<div @click="clickStatus($event,item)">
								<img :src="require('../assets/images/'  +item.icon_none + '.png')" class="imgs1"
									v-if="item.status === '0'" />
								<span>{{item.name}}</span>
							</div>
						</template>
						<!-- 二级菜单 -->
						<template v-for="itemChild in item.children">
							<el-menu-item :index="itemChild.router" :key="itemChild.router">
								<span slot="title" class='submenu'>{{itemChild.name}}</span>
							</el-menu-item>
						</template>
					</el-submenu>
					<el-menu-item v-else :index="item.router" :key="item.router" @open="open" ref="elMenu"
						class="list_two">
						<div @click="clickStatus($event,item)">
							<img :src="require('../assets/images/'  +item.icon_none + '.png')" class="imgs1"
								v-if="item.status === '0'" />
							<span slot="title">{{item.name}}</span>

						</div>
					</el-menu-item>
				</template>
			</el-menu>
		</div>

	</div>
</template>
<script>
	import {studentsList} from "../assets/js/studentsList";
	import {parentList} from '../assets/js/parentList'
	import {teacherList} from '../assets/js/teacherList'
	export default {
		name: "sidebar",
		data() {
			return {
				isUnique: true,
				isRouter: true,
				navData: [],
				NavActive: "",
			};
		},
		beforeMount() {
			this.getActiveNav();
		},
		watch: {
			//监听路由变化
			$route(index) {
				// console.log('sideBarRouter',index)
				let path = index.path.substr(1);
				this.handleSelect(path);
			},
		},
		created() {
			// this.navData = JSON.parse(localStorage.menus);
		},
		mounted() {
			let userVal = sessionStorage.getItem("userVal");
			if(userVal==0){
				this.navData = studentsList.list;
				this.$router.push({path:'/studentHome'})
			}else if(userVal==1){
				this.navData = parentList.list;
				this.$router.push({path:'/parentHome'})
			}else if(userVal==2){
				this.navData = teacherList.list
				this.$router.push({path:'/teacherHome'})
			}
			// console.log(sessionStorage.getItem("isGarden") === "0");
			// console.log(sessionStorage.getItem("isGarden") === "1");
			// // isGarden === 0 为园区端;isGarden === 1 为企业端
			// if (sessionStorage.getItem("isGarden") === "0") {
			// 	this.navData = navDataList.list;
			// } else if (sessionStorage.getItem("isGarden") === "1") {
			// 	this.navData = navdataa.list;
			// }
		},
		methods: {
			getActiveNav() {
				let currentUrl = window.location.href;
				this.NavActive = currentUrl.split("/").pop();
			},
			//监听路由的变化,对应菜单高亮显示
			handleSelect(index) {
				this.NavActive = index;
			},
			clickStatus(e, item) {
				// console.log(e,item)
				// console.log(this.$refs.elMenu)
				// this.$refs.elMenu.map((item1) => {
				//   console.log(item1.$el)
				//   // if(item1.active === false){

				//   // }
				// })
			},
			open() {
				console.log("1");
			},
		},
	};
</script>
<style scoped lang="less">
	.sidebar_wrap {
		width: 1.4583rem;
		height: 100%;
		// background: #870000;
		background: #fff;
		overflow-y: auto;
		overflow-x: hidden;

		.wrap_title {
			display: flex;
			align-items: center;
			justify-content: center;
			font-size: 0.1111rem;
			color: #fff;
			height: 0.5556rem;

			img {
				width: 0.2778rem;
				height: 0.1528rem;
				margin-right: 0.0764rem;
			}
		}

		.wrap_catalog {
			/deep/ .el-menu {
				border-right: none;
				// background-color: #870000;
				background-color: #fff;
				width: 1.4583rem;

				li {
					padding: 0 !important;
				}

				.el-menu-item {
					height: 0.3056rem;
					line-height: 0.3056rem;
					font-size: 0.1111rem;
					color: #0E151E;
					// border-bottom: 0.0069rem solid #a43d3d;
				}

				.el-submenu__title {
					height: 0.3056rem;
					line-height: 0.3056rem;
					font-size: 0.1111rem;
					// color: #0E151E;
					// border-bottom: 0.0069rem solid #a43d3d;
				}

				.el-submenu__icon-arrow {
					display: none;
				}

				.el-menu-item.is-active {
					width: 1.4583rem;
					height: 0.3056rem;
					color: #FFFFFF;
					padding-left: 0.6944rem;
					// background: #B40024;
					// background: url("../assets/new_images/xuanzhong.png") no-repeat;
					background-color: #D9221A;
					// background-position: 0.0694rem 0.0486rem;
				}

				.el-menu-item:hover {
					// background: #B40024;
					background-color: #D9221A;
					color: #fff;
					// background: url("../assets/new_images/xuanzhong.png") no-repeat;
					// background-position: 0.0694rem 0.0486rem;
				}

				.el-submenu.is-active.is-opened {
					// background: #B40024;
					// background: url("../assets/new_images/xuanzhong.png") no-repeat;
					// background-position: 0.0694rem 0.0486rem;
					background-color: #D9221A;
					color: #fff;

					.el-menu-item.is-active {
						// background: #A20A1E;
						background-color: #D9221A;
						color: #fff;
					}

					.el-menu-item:hover {
						// background: #A20A1E;
						background-color: #D9221A;
						color: #fff;
					}
				}

				.el-submenu:hover {
					.el-menu-item:hover {
						// background: #A20A1E;
						background-color: #D9221A;
						color: #fff;
					}
				}

				.el-submenu__title:hover {
					// background: #B40024;
					// background: url("../assets/new_images/xuanzhong.png") no-repeat;
					// background-position: 0.0694rem 0.0486rem;
					background-color: #D9221A;
					color: #fff;

					.el-menu-item:hover {
						// background: #A20A1E;
						background-color: #D9221A;
						color: #fff;
					}
				}

				.el-submenu.is-opened:hover {
					// background: #B40024;
					// background: url("../assets/new_images/xuanzhong.png") no-repeat;
					// background-position: 0.0694rem 0.0486rem;
					background-color: #D9221A;
					color: #fff;

					.el-menu-item:hover {
						// background: #A20A1E;
						background-color: #D9221A;
					}
				}

				.imgs1 {
					width: 0.1389rem;
					height: 0.1389rem;
					margin-right: 0.0347rem;
				}

				.submenu {
					font-family: 'PingFang-Regular';
				}
			}

			.list_one:last-child {

				// border-bottom: 0.0069rem solid #870000;
				/deep/ .el-menu-item:last-child {
					// border-bottom: 0.0069rem solid #870000;
				}
			}

			.list_two:last-child {
				// border-bottom: 0.0069rem solid #870000;
			}
		}
	}
</style>

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

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

// 导航栏信息
// 一级导航index要与其子代(二级)导航第一个index相同
// name: 菜单要显示的名字
// index: 导航地址(router中的名字)
// img: 图标名字(用class定义)
// children: 迭代子代导航、参数如上
// 教师端
export const teacherList = {
	"list": [
        {
            "name": "健康测评",
            "name_en": "teacherHome",
            "router": "/teacherHome",
            "icon_none": "shouyeIcon_255",
            "icon_block": "shouyeIcon_255",
            "status": '0',
            "children": [],
        },{
            "name": "心理测评",
            "name_en": "psychometrics",
            "router": "/psychometrics",
            "icon_none": "shouyeIcon_255",
            "icon_block": "shouyeIcon_255",
            "status": '0',
            "children": [],
        },{
            "name": "教学资源",
            "name_en": "teachResources",
            "router": "/teachResources",
            "icon_none": "shouyeIcon_255",
            "icon_block": "shouyeIcon_255",
            "status": '0',
            "children": [],
        },{
			"name": "在线研修",
			"name_en": "autonomouslyStudy",
			"router": "/autonomouslyStudy",
			"icon_none": "shouyeIcon_255",
			"icon_block": "shouyeIcon_255",
			"status": '0',
			"children": [
                {
                    "name": "自主学习",
                    "name_en": "autonomouslyStudy",
                    "router": "/autonomouslyStudy",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
                {
                    "name": "教师调研",
                    "name_en": "teacherResearch",
                    "router": "/teacherResearch",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
                {
                    "name": "直播培训",
                    "name_en": "liveTraining",
                    "router": "/liveTraining",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
                {
                    "name": "在线阅读",
                    "name_en": "onlineReading",
                    "router": "/onlineReading",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
                {
                    "name": "课程研究",
                    "name_en": "projectResearch",
                    "router": "/projectResearch",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
                {
                    "name": "展示交流",
                    "name_en": "displayCommunication",
                    "router": "/displayCommunication",
                    "icon_none": "shouyeIcon_255",
                    "icon_block": "shouyeIcon_255",
                    "status": '0',
                    "children": [],
                },
            ],
		},
	]
}

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

sider.vue

<script lang="ts" setup>
// sidebarItem 项组件
import SideBarItem from './sidebarItem.vue';
import { useRouter } from 'vue-router';
// 拿到路由列表,过滤我们不想要的
const router = useRouter();
const routerList = router.getRoutes().filter((v) => v.meta && v.meta.isShow);
</script>
<template>
  <div class="sidebar">
    <!-- 项目名称及logo -->
    <div class="sidebar-logo flex-center">
      <svg-icon icon-class="logo" />
      <span>VitalityAdmin</span>
    </div>

    <!-- 导航菜单 -->
    <el-menu
        active-text-color="#fff"
        background-color="#001529"
        :default-active="$route.path"
        text-color="#999"
        :unique-opened="true"
        router>

      <!-- 引入子组件 -->
      <SideBarItem :routerList="routerList" />
    </el-menu>

    <!-- active-text-color:当前菜单项被选中时,字体的颜色 -->
    <!-- background-color:这个menu菜单的背景色 -->
    <!-- default-active:	当前激活菜单的 index -->
    <!-- text-color:菜单项字体颜色 -->
    <!-- unique-opened:unique-opened	是否只保持一个子菜单的展开 -->
    <!-- router:是否使用 vue-router 的模式,启用该模式会在激活导航时以 index 作为 path 进行路由跳转 -->
  </div>
</template>
<style lang="scss" scoped>
.sidebar {
  height: 100%;
  .sidebar-logo {
    height: 48px;
    background-color: #002140;
    color: #fff;
    font-weight: 700;
    line-height: 48px;
    text-align: center;
    font-size: 20px;
  }
  .el-menu {
    height: calc(100% - 48px);
    border-right: 0;
    overflow: auto;
  }
}
</style>

sidebarItem.vue

<script setup lang="ts">
import { RouteRecordRaw } from 'vue-router';
// 做类型限制,解决ts类型报错
type CustomRouteRecordRaw = RouteRecordRaw & {
  meta: {
    isShow?: boolean;
  };
};
const props = defineProps({
  // 拿到父组件传递过来的路由列表进行渲染
  routerList: {
    type: Array as () => CustomRouteRecordRaw[],
    required: true
  }
});
</script>
<template>
  <template v-for="item in props.routerList" :key="item.path">
    <!-- 当该菜单项有子菜单时 -->
    <el-sub-menu :index="item.path" v-if="item.children && item.children.length > 0">
      <template #title v-if="item.meta.icon">
        <!-- 菜单项图标,我此处用的是全局封装的 svg组件 -->
        <el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
        <!-- 菜单项名称,在路由中定义好 -->
        <span>{{ item.meta.title }}</span>
      </template>
      <!-- 若路由中未定义菜单项icon,则仅展示名称--(我的仅一级菜单有图标) -->
      <template #title v-else>{{ item.meta.title }}</template>

      <!-- 递归遍历-自己调用自己(核心代码) -->
      <sidebarItem :routerList="( item.children as CustomRouteRecordRaw[])" />
    </el-sub-menu>

    <!-- 当前菜单项无子菜单 -->
    <el-menu-item :index="item.path" v-else>
      <!-- 与上面注释大致相同,不多做额外注释 -->
      <template v-if="item.meta.icon">
        <el-icon><svg-icon :icon-class="item.meta.icon" /></el-icon>
        <span>{{ item.meta.title }}</span>
      </template>
      <template v-else>
        {{ item.meta.title }}
      </template>
    </el-menu-item>
  </template>
</template>

<style scoped lang="scss">
.is-active {
  background: #409eff;
  font-weight: 700;
}

.el-menu-item {
  &:hover {
    color: #fff;
    font-weight: 700;
  }
}

.el-menu--collapse {
  .el-menu-item {
    justify-content: center;
  }
}

// 下列代码是用于兼容horizontal所写,酌情删或留
.el-menu--horizontal {
  .el-menu-item.is-active {
    background-color: transparent !important;
    border-bottom: 2px solid #409eff !important;

    .el-icon,
    span {
      color: #409eff !important;
    }
  }

  .el-sub-menu.is-active {
    .el-sub-menu__title {
      border: 0 !important;
    }

    .el-icon,
    span {
      color: #409eff !important;
    }
  }
}
</style>

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值