vue2.0 @scroll滚动事件实现左右联动效果

本文分享了在前端开发中,如何实现右侧列表滚动时左侧步骤条节点的同步显示及点击左侧节点显示对应内容的功能。通过监听滚动事件和点击事件,结合计算每个子盒子距离顶部的高度,实现了列表滚动与步骤条的完美同步。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言:在实际开发中,我们经常碰到需要滚动右边列表,左边步骤条节点对应显示,点击左边节点右边显示对应内容;今天小编就碰到了这样的需求,在公司大佬的指引下,顺利完成,特此记录一篇,哎,前端水好深,一不小心就被淹死了,,,无情,冷酷,但是还有加油!!!!

思路: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;
                      } 
                }
            }  
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

布依前端

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值