效果:
代码:
interface IProps{
titleList: IEachTitle[];
onSave: () => void;
}
interface IEachTitle{
name: string;
content: React.ReactNode;
}
export const ContentFrame = (props: IProps) => {
const { titleList, onSave } = props;
const [
selectedTitle,
setSelectedTitle,
] = useState(titleList[0].name);
const onMenuChange = (name) => {
const titleEle = document.getElementById(name);
const scrollContainer = document.querySelector('#container');
const titleTop = titleEle.getBoundingClientRect().top + scrollContainer.scrollTop - 16;
scrollContainer.scrollTo({ top: titleTop });
setSelectedTitle(name);
};
// 页面滚动自动选中右边定位板菜单
const onContainerScroll = (e) => {
const scrollContainer = e.target;
const divList = Array.from(scrollContainer.firstElementChild.children);
const viewHeight = window.innerHeight;// 视口高度
const inviewFirstDiv = divList.find((item: HTMLDivElement) => {
const rectDiv = item.getBoundingClientRect();
// 判断块是否在视口范围
if ((rectDiv.top > 0 && rectDiv.top < (viewHeight - 48)) || (rectDiv.top < 0 && Math.abs(rectDiv.top) < rectDiv.height - 16)) {
return true;
}
return false;
});
// @ts-ignore
const selectedTitle = inviewFirstDiv.firstElementChild.getAttribute('id');
setSelectedTitle(selectedTitle);
};
return (
<div className={styles.container}>
<div
className={styles.contentContainer}
id="container"
onScroll={_.throttle(onContainerScroll, 500)}
>
<div className={styles.content}>
{
titleList.map((item) => {
return (
<div key={item.name}>
<div
className={`${styles.titleFont} ${styles.contentTitle}`}
id={item.name}
>
<div className={styles.decorateStripe}/>
{item.name}
</div>
<div className={styles.contentWrapper}>
{item.content}
</div>
</div>
);
})
}
</div>
</div>
<div className={styles.buttonWrapper}>
<Button
onClick={() => onSave()}
type="primary"
>
保存
</Button>
</div>
<div className={styles.menu}>
{
titleList.map((item) => {
return (
<div
className={`${styles.menuItem} ${selectedTitle === item.name && styles.selectMenuItem}`}
key={item.name}
onClick={() => {
onMenuChange(item.name);
}}
>
{item.name}
</div>
);
})
}
</div>
</div>
);
};