react 电商联动demo
import React, { FC, useEffect, useState } from 'react'
import './index.less'
interface IProps {
datas: Array<IPropsDatas>;
leftRow: (paramItem: IPropsItem) => JSX.Element;
rightRow: (paramItem: IPropsItem) => JSX.Element;
classNames?: string
}
interface IPropsItem {
title: string;
key: string;
}
interface IPropsDatas {
left: Array<IPropsItem>;
right: Array<IPropsItem>;
}
// const datas = [
// { left: { title: 'AAA', key: 't1a' }, right: [{ title: 'AAA', key: 'AAA' }] },
// ]
// const leftRow = (paramItem: any) => (
// <div className=''>{paramItem}</div>
// )
// const rightRow = (paramItem: any) => (
// <div className=''>
// {paramItem}
// <div className=''>ceshi</div>
// </div>
// )
let tabLeftInit: Array<IPropsItem[]> = [];
let tabRightInit: Array<IPropsItem[]> = [];
let right: number[] = []
let rightSum: number[] = []
let left: number[] = []
let leftSum: number[] = []
let newIndex: number = 0
let itemEleRight: any = null;
let itemEleLeft: any = null;
let listEleWrap: any = null;
const getEle = (ele: string) => {
const itemHeiList: any = []
const itemEle = document.querySelectorAll(ele)
itemEle.forEach((item: any) => {
itemHeiList.push(item.offsetHeight)
})
return itemHeiList
}
const getEleSum = (ele: number[]) => {
const sumArr: number[] = []
const sum = ele.reduce((total: number, num: number) => {
const sumItem = total + num
sumArr.push(sumItem)
return sumItem
}, 0)
return sumArr
}
const AboutLinkage: FC<IProps> = (props: IProps): JSX.Element => {
let { datas, leftRow, rightRow, classNames = '' } = props;
const [stateIndex, setStateIndex] = useState(newIndex)
const [tabLeft, setStateTabLeft] = useState(tabLeftInit)
const [tabRight, setStateTabRight] = useState(tabRightInit)
const splitList = (datas: Array<IPropsDatas>) => {
const listL: Array<IPropsItem> = []
const listR: Array<IPropsItem[]> = []
datas.forEach((item: any) => {
listL.push(item.left)
listR.push(item.right)
})
setStateTabLeft([listL])
setStateTabRight(listR)
}
// 点击右侧滚动
const handleClick = (items: any, seat: any) => {
let num = 0;
if (items === newIndex) return
newIndex = items
for (let i = 0; i < items; i++) {
num += right[i];
}
if (itemEleRight.length > 0) {
const el = itemEleRight[0]
el && el.scrollTo({
top: num,
left: 0,
behavior: "smooth"
})
}
}
// 渲染列表
const fnCreateList = (dataList: Array<IPropsItem[]>, seat?: string) => (
<div className={`about-linkage-list-wrap${classNames && -classNames}`}>
{dataList.map((item: IPropsItem[], index: number) => {
return (
<ul className={`about-linkage-list${classNames && -classNames}`} key={index} >
{item.map((item: any, index: number) => (
<li
key={'' + index + seat}
className={(stateIndex === index) && seat ?
`about-linkage-item${classNames && -classNames} active${classNames && -classNames}` :
`about-linkage-item${classNames && -classNames}`}
onClick={() => {if (seat) handleClick(index, 1)}}
>
<div className={`item-text${classNames && -classNames}`}>
{
seat ?
leftRow && leftRow(item.title) :
rightRow && rightRow(item.title)
}
</div>
</li>)
)}
</ul>
)}
)}
</div>
)
// 监听滚动事件
const onscroll = function () {
let scollTopNumR = itemEleRight[0].scrollTop
let keyR = rightSum.findIndex((item: number) => item > scollTopNumR) || 0
if (keyR < 0) keyR = 0
let keyLVal = leftSum[(keyR - 1)] || 0 // 左侧滚动标识位
let keyLValNext = leftSum[(keyR)] || 0 // 左侧滚动判断标识位
const numScrollSumR = scollTopNumR + itemEleRight[0].offsetHeight // 右侧滚动高度位置
const numSumR = listEleWrap[1].offsetHeight// 左侧高度L
if (numScrollSumR < numSumR) {
setStateIndex(keyR)
newIndex = keyR
} // 左侧选中判断
const elL = itemEleLeft[0]
if (keyLValNext > elL.offsetHeight) {
elL && elL.scrollTo({
top: keyLVal - (elL.offsetHeight / 2),
left: 0,
behavior: "smooth"
})
}
if ((keyLValNext < elL.offsetHeight) && (elL.scrollTop !== 0)) {
elL && elL.scrollTo({
top: 0,
left: 0,
behavior: "smooth"
})
}
}
useEffect(() => {
datas && splitList(datas)
setTimeout(() => {
right = getEle(`.about-linkage-right${classNames && -classNames} .about-linkage-list${classNames && - classNames}`)
left = getEle(`.about-linkage-left${classNames && -classNames} .about-linkage-item${classNames && -classNames}`)
rightSum = getEleSum(right)
leftSum = getEleSum(left)
itemEleRight = document.body.querySelectorAll(`.about-linkage-right${classNames && -classNames}`)
itemEleLeft = document.body.querySelectorAll(`.about-linkage-left${classNames && -classNames}`)
listEleWrap = document.body.querySelectorAll(`.about-linkage-list-wrap${classNames && -classNames}`)
}, 0)
return () => {
// cleanup
right = []
rightSum = []
left = []
leftSum = []
newIndex = 0
itemEleRight = null;
itemEleLeft = null;
listEleWrap = null;
}
}, [datas, classNames])
return (
<div className={`about-linkage-wrap${classNames && -classNames}`}>
<div className={`about-linkage-left-wrap${classNames && -classNames}`}>
<div className={`about-linkage-left${classNames && -classNames}`}>
{fnCreateList(tabLeft, '1')}
</div>
</div>
<div
className={`about-linkage-right${classNames && -classNames}`}
onScroll={onscroll}
>
{fnCreateList(tabRight, '')}
</div>
</div>
)
}
export default Demo
style
@width: 200px;
@height: 32vh;
@leftHeight: 100px;
@scrollBarWidth: 16px;
@flagWidth: 6px;
.about-linkage-wrap {
width: 100%;
height: @height;
background: pink;
position: relative;
z-index: 2;
.about-linkage-left-wrap {
position: absolute;
width: @width;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
z-index: 2;
}
.about-linkage-left {
background: #bfa;
padding-right: @scrollBarWidth;
width: calc(@width + @scrollBarWidth);
height: @height;
overflow-y: scroll;
}
.about-linkage-right {
position: absolute;
left: 0;
top: 0;
padding-left: @width;
width: 100%;
height: @height;
z-index: 1;
overflow-y: scroll;
&::-webkit-scrollbar {
display: none;
}
}
}
.about-linkage-list-wrap {
width: 100%;
.about-linkage-list {
width: 100%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.about-linkage-item {
width: 100%;
min-height: @leftHeight;
display: flex;
justify-content: flex-start;
align-items: center;
padding-right: @flagWidth;
border:1px solid #ccc;
.item-text {
width: 100%;
height: 100%;
}
}
.active {
color: #fff;
background: pink;
}
}
}
网友评论