Vue simple sidebar encapsulation + simulated sidebar labels fade in and out

Project scenario:

提示:这里简述项目相关背景:

Click the label to jump to the corresponding page, of course, it can be realized with router-link and router-view.
Here we use other methods to simulate the fading in and out of the side navigation bar after clicking


solution:

1. Encapsulate a custom sidebar

In this case, the menus are all first-level directories, so only ul/lia custom simple list is used here. (If you have other needs, you are willing to use el-menu and write it yourself)
1. Create the component SelfMenu.vue

<template>
	<div>
		<ul class="self-page-menu">
			<li v-for="(item,i) in pageMenu" :key="item.id" @click="changePage(item.id)" :class="{'self-active-node':activeNode==i}">{
    
    {
    
    item.name}}<i class="el-icon-caret-right self-icon"></i></li>
		</ul>
	</div>
</template>
<script>
export default {
    
    
	props:{
    
    
		pageMenu:{
    
    
			type:Array,
			default:()=>[]
		}
	},
	data(){
    
    
		return {
    
    
			activeNode:0
		}
	},
	methods:{
    
    
		changePage(i){
    
    
			this.activeNode = i;
			this.$emit("switchPageMenu",this.activeNode)
		}
	}
}
</script>
<style lang="scss" scoped>
.self-page-menu{
    
    
	list-style:none;
	padding:0;
	margin:0;
	li{
    
    
		cursor:pointer;
		color:#666;
		font-size:16px;
		height:50px;
		padding:17px 40px 14px;
		vertical-align:text-top;
		.self-icon{
    
    
			float:right;
		}
	}
	.self-active-node{
    
    
		color:#1355FD;
		background-color:#E9EDFD;
	}
}
</style>

2. The subpage fades in and out and the sidebar changes with the height of the subpage

Take A and B as two subpages (assuming that page A has less content, which is less than the page scrolling threshold ; B has more content, which is greater than the scrolling threshold ), the total page is index.vue
1, A, B subpage
A page

<template>
	<div>这是A页面</div>
</template>
<script>
export default {
      
      }
</script>

Page B

<template>
	<div>这是B页面<h1>内容</h1>(。。。省略300行)</div>
</template>
<script>
export default {
      
      }
</script>

2、index.view

<template>
	<div style="height:100%">
		<div class="main-area" ref="pageWrap">
			<div class="bg p-left">
				<self-menu @switchPageMenu="switchMenu" :page-menu="pageMenu"></self-menu>
			</div>
			<div class="p-right" ref="pageHeight">
				<template v-if="recentPage==0">
					<transition name="fade-transform" mode="out-in">
						<div :key="0" class="back right-item"><page-a></page-a></div>
					</transition>
				</template>
				<template v-if="recentPage==1">
					<transition name="fade-transform" mode="out-in">
						<div :key="1" class="back right-item"><page-b></page-b></div>
					</transition>
				</template>
			</div>
		</div>
	</div>
</template>
<script>
import SelfMenu from "./components/SelfMenu.vue";
import pageA from "./A.vue";
import pageB from "./B.vue";
export default {
      
      
	components:{
      
      pageA,pageB},
	data:{
      
      
		return {
      
      
			recentPage:0,
			minPageHeight:0,//高度记录
			pageMenu:[{
      
      name:'A页面',id:0},{
      
      name:'B页面',id:1}]
		}
	},
	mounted(){
      
      
		this.getHeight();//此处监听被子页面称起父元素的高度,来决定菜单高度
		window.onresize = () => {
      
      
			this.minPageHeight = this.$refs.pageWrap.clientHeight;
			this.setTimeOut(() => {
      
      this.getHeight(), 500})
		}
	},
	methods:{
      
      
		switchMenu(data){
      
      
			this.recentPage = data;
			this.getHeight();
		},
		getHeight(){
      
      //实现侧边栏随子页面高度变化效果
			//由于父元素min-height属性无法继承高度,所以需手动给右测父元素添加height属性
			if(!this.recentPage){
      
      //这里判断高度小于滚动临界值的所有页面,例如A页面
				this.$refs.pageHeight.style.height = this.minPageHeight + 'px';
			} else {
      
      //这里判断高度大于滚动临界值的所有页面,例如B页面
				this.$refs.pageHegith.style.height = 'auto';
			}
		}
	}
}
</script>
<style lang="scss" scoped>
//过渡效果
.fade-transform-leave-active,
.fade-transform-enter-active {
      
      
  transition: all .5s;
}

.fade-transform-enter {
      
      
  opacity: 0;
  transform: translateX(-30px);
}

.fade-transform-leave-to {
      
      
  opacity: 0;
  transform: translateX(30px);
}
//板块背景
.back{
      
      
	background-color:#fff;
	border-radius:10px;
}
.main-area{
      
      
	//margin间距包括顶栏共123px,所以保证子页面高度不够情况时,最小高度为滚动临界值
	min-height:calc(100% - 123px);
	box-sizing:border-box;
	position:relative;
	.p-left{
      
      
		position:absolute;
		min-height:100%;
		width:280px;
		padding-top:40px;
	}
	.p-right{
      
      
		min-height:100%;//限制右侧最小高度
		width:calc(100% - 290px);//与左边菜单栏相隔10px
		margin-left:290px;
		.right-item{
      
      
			height:auto;//不限制嵌套子页面高度
			min-height:100%;
			padding:23px 30px 39px 30px;
		}
	}
}
</style>

Guess you like

Origin blog.csdn.net/weixin_43939111/article/details/128612031