- 样式方面 左右固定 添加overflow-y: scroll属性
- index.less
.Linkage-Box {
width: 100vw;
height: 100vh;
display: flex;
overflow: hidden;
.Linkage-Box-left::-webkit-scrollbar {
display: none;
}
.Linkage-Box-left {
width: 25vw;
background-color: skyblue;
overflow-y: scroll;
scroll-behavior: smooth;
>div {
width: 100%;
height: (100vh / 8);
text-align: center;
line-height: (100vh / 8);
border-bottom: 0.5px solid #000;
}
}
.Linkage-Box-right::-webkit-scrollbar {
display: none;
}
.Linkage-Box-right {
width: 75vw;
background-color: pink;
overflow-y: scroll;
scroll-behavior: smooth;
>div {
width: 100%;
height: 80vh;
border-bottom: 0.5px solid #000;
}
}
}
.action2 {
background-color: pink;
}
- 逻辑 index.tsx
import React, { useEffect, useRef, useState } from 'react'
import "./index.less"
export default function Linkage() {
const tit = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
const [leftin, setleftin] = useState<number>(0);
const [flag, setflag] = useState<boolean>(true);
const rightbox = useRef<HTMLDivElement | null>(null);
const leftbox = useRef<HTMLDivElement | null>(null);
let height: number = 0
let RightBoxHe: number = 0
let sequence: number[] = []
useEffect(() => {
RightBoxHe = (getright().children[0] as HTMLDivElement).offsetHeight
sequence.push(height);
getright().childNodes.forEach((item) => {
height += (item as HTMLDivElement).offsetHeight
sequence.push(height);
})
})
const handel = (index: number) => {
setflag(false);
setleftin(index);
getright().scrollTop = index * RightBoxHe;
getleft().scrollTop = index >= 4 ? (index - 3) * 93 : 0
}
const Fnscroll = () => {
if (flag === false) return false
sequence.forEach((item, index) => {
if (getright().scrollTop >= item - 10) {
setleftin(index);
getleft().scrollTop = index >= 4 ? (index - 3) * 93 : 0
}
})
}
const fnend = () => setflag(true);
const getright = () => rightbox.current as HTMLDivElement
const getleft = () => leftbox.current as HTMLDivElement
return (
<div className='Linkage-Box'>
<div className="Linkage-Box-left" ref={leftbox}>
{tit.map((item, index) => <div key={item} onTouchStart={() => handel(index)} className={leftin === index ? "action2" : ""}>
{item}
</div>)}
</div>
<div className="Linkage-Box-right" ref={rightbox} onScroll={Fnscroll} onTouchStart={fnend}>
{tit.map((item, index) => <div key={item}>
{item}
</div>)}
</div>
</div>
)
}
以上就是关于美团二级联动 的相关逻辑了 ,如有问题评论区@博主;
核心思路是:传入左边按钮的下标 通过点击控制右边scrollTop动,值=小标+右边子盒子的高
右边:在useEffect中提前将右边每个子盒子距离顶部的距离存入一个数组中,然后在scroll事件中
判断大盒子的距离顶部的滚动距离也就是scrollTop 是否大于每个盒子距离顶部的距离 如大于证明你滚动到了相应的盒子,此时吧数组中对应的下标传给左边,来控制左边动;
我在逻辑中添加了运动效果,感兴趣的朋友可以去查找相关的文章阅读;