前言:在实际开发中,我们经常碰到需要滚动右边列表,左边步骤条节点对应显示,点击左边节点右边显示对应内容;今天小编就碰到了这样的需求,在公司大佬的指引下,顺利完成,特此记录一篇,哎,前端水好深,一不小心就被淹死了,,,无情,冷酷,但是还有加油!!!!
思路:1、@scroll=“handleScroll”:监听父元素滚动事件,用来计算每个子盒子的距离顶部的高度;
2、@click=“handleClick(idx)”:点击左边节点显示对应页面内容;
效果图:注意:表单内容需要到子盒子里 .content_box 添加,代码里没给出,给了页面结构;
1、页面结构
<template>
<div class="sys_emp_detail">
<div class="container_wrap">
<div class="left_box">
<div class="step_box" v-for="(item,idx) in stepsList" :key="idx">
<div class="text" @click="handleClick(idx)" :class="idx ==index?'current-text':''">{{item.title}}</div>
<template v-if="idx<stepsList.length-1">
<div class="circle" :class="index==idx?'current-back':''"></div>
</template>
<template v-else-if="idx==stepsList.length-1">
<div class="circle end" ></div>
</template>
</div>
</div>
<div class="right_box" ref="itemList">
<div class="head_title" :style="index>0?'box-shadow: 0px 3px 2px 0px rgba(84, 151, 215,.2);':''">
<h2>{{list.name}}个人信息{{state?'编辑':'详情'}}</h2>
<Button @click="toBack">返回</Button>
</div>
<div class="content_big_right" @scroll="handleScroll" ref="rigth">
<!-- 基本信息 -->
<div class="content_box">
<div class="label_box">
<h3>基本信息</h3>
<p v-if="state&&!section.info" @click="handleEdit('info')">编辑</p>
</div>
</div>
<!-- 个人信息 -->
<div class="content_box">
<div class="label_box">
<h3>个人信息</h3>
<p v-if="state&&!section.personInfo" @click="handleEdit('personInfo')">编辑</p>
</div>
</div>
<!-- 学历信息 -->
<div class="content_box" v-for="(item,index) in educationList" :key="index">
<div class="label_box">
<h3>学历信息({{index+1}})</h3>
<p v-if="state&&!section.education" @click="handleEdit('education')">编辑</p>
<p v-if="section.education && index>0" @click="handleDelete(index,'education')">删除</p>
</div>
</div>
<!-- 银行卡信息 -->
<div class="content_box">
<div class="label_box">
<h3>银行卡信息</h3>
<p v-if="state&&!section.bank" @click="handleEdit('bank')">编辑</p>
</div>
</div>
<!-- 紧急联系人 -->
<div class="content_box">
<div class="label_box">
<h3>紧急联系人</h3>
<p v-if="state&&!section.bank" @click="handleEdit('bank')">编辑</p>
</div>
</div>
<!-- 家挺信息 -->
<div class="content_box" v-for="(item,index) in familyList" :key="index">
<div class="label_box">
<h3>家庭信息({{index+1}})</h3>
<p v-if="state&&!section.family" @click="handleEdit('family')">编辑</p>
<p v-if="section.family && index>0" @click="handleDelete(index,'family')">删除</p>
</div>
</div>
<!-- 个人材料 -->
<div class="content_box">
<div class="label_box">
<h3>个人材料</h3>
<p v-if="state&&!section.person" @click="handleEdit('person')">编辑</p>
</div>
</div>
<!-- 校招材料 -->
<div class="content_box">
<div class="label_box">
<h3>校招材料</h3>
<p v-if="state&&!section.society" @click="handleEdit('society')">编辑</p>
</div>
</div>
<!-- 备注 -->
<div class="content_box">
<div class="label_box">
<h3>备注</h3>
<p v-if="state&&!section.remark" @click="handleEdit('remark')">编辑</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: "Detail",
data(){
return{
stepsList:[
{title:'基本信息'},
{title:'个人信息'},
{title:'学历信息'},
{title:'银行卡信息'},
{title:'紧急联系人'},
{title:'个人材料'},
{title:'校招材料'}
],
scrollY:0,//右侧列表滑动的y轴坐标
rightBscroll:-1,
index: 0
}
},
watch: {
scrollY(){
this.initRightBoxHeight();
//console.log(11);
}
},
methods:{
handleScroll(event){
this.scrollY = event.target.scrollTop;
},
handleClick(idx){
this.index = idx;
this.initRightBoxHeight();
this.$refs.rigth.scrollTop = this.rightLiTops[idx];
},
/*计算每个小盒子高度*/
initRightBoxHeight(){
let itemArray=[];
let top = 0;
itemArray.push(top)
//获取右边所有子盒子高度集合
let allList = this.$refs.itemList.getElementsByClassName('content_box');
//allList伪数组转化成真数组
Array.prototype.slice.call(allList).forEach(li => {
top += li.clientHeight; //获取所有li的每一个高度
itemArray.push(top)
});
this.rightLiTops = itemArray;
this.rightLiTops.forEach((item,index)=>{
if(item<=this.scrollY)
{
this.index = index;
}
})
//console.log(this.index,this.scrollY);
},
}
}
</script>
<style src="./style.less" lang="less" scoped></style>
2 . css样式
.sys_emp_detail{
.container_wrap{
display: flex;
.left_box {
min-width: 48px;
padding: 180px 0 0 80px;
.step_box{
display: flex;
justify-content: center;
align-items: center;
min-width: 122px;
height: 53px;
.current-text{
color:#5497D6 !important;
}
.current-back{
background-color: #5497D6 !important;
}
.text{
padding-right: 5px;
font-size: 9px;
width: 65px;
color: #333333;
text-align: right;
cursor: pointer;
}
.circle{
width: 8px;
height: 8px;
border-radius: 50%;
background-color: rgba(204,204,204,1);
position: relative;
}
.circle::after{
content:'';
height: 45px;
width: 1px;
display: inline-block;
border-right: 1px solid #CCCCCC;
position: relative;
left: 4px;
top: 8px;
}
.end::after{
content: '';
display: none;
}
}
}
.right_box {
flex: 1;
//width: 800px;
.head_title{
position: relative;
h2{
font-size:18px;
color: #333333;
text-align: center;
padding: 10px 0 30px;
}
button{
font-size: 14px;
color: #fff;
background-color: #5497D6;
position: absolute;
top: 5px;
right: 0;
border-radius:4px;
cursor: pointer;
}
}
.content_big_right{
max-height: 689px;
overflow-x: hidden;
padding: 0 25px;
}
.content_box{
.label_box{
display: flex;
justify-content: space-between;
background-color: #F2F2F2;
line-height: 46px;
h3{
color: #333333;
font-size:14px;
padding: 0 15px;
}
p{
font-size: 14px;
color: #5497D6;
padding: 0 15px;
cursor: pointer;
}
}
}
}
}
}