index.tsx中
import { Component, createRef } from "react";
import './index.less'
interface Props {
}
interface NavListType {
ID: string,
Content: string
}
interface ContentListType {
ID: string,
Content: string
}
interface State {
Index: number,
NavList: NavListType[],
ContentList: ContentListType[],
// 用来判断是否监听滚动
listBoxState: boolean
}
class LinkAge extends Component<Props, State>{
constructor(props: Props) {
super(props);
this.state = {
Index: 0,
NavList: [
{ ID: "nav1", Content: "按钮1" },
{ ID: "nav2", Content: "按钮2" },
{ ID: "nav3", Content: "按钮3" },
{ ID: "nav4", Content: "按钮4" },
{ ID: "nav5", Content: "按钮5" },
{ ID: "nav6", Content: "按钮6" },
{ ID: "nav7", Content: "按钮7" },
{ ID: "nav8", Content: "按钮8" },
{ ID: "nav9", Content: "按钮9" },
{ ID: "nav10", Content: "按钮10" },
{ ID: "nav11", Content: "按钮11" },
{ ID: "nav12", Content: "按钮12" },
{ ID: "nav13", Content: "按钮13" }
],
ContentList: [
{ ID: "content1", Content: "内容1" },
{ ID: "content2", Content: "内容2" },
{ ID: "content3", Content: "内容3" },
{ ID: "content4", Content: "内容4" },
{ ID: "content5", Content: "内容5" },
{ ID: "content6", Content: "内容6" },
{ ID: "content7", Content: "内容7" },
{ ID: "content8", Content: "内容8" },
{ ID: "content9", Content: "内容9" },
{ ID: "content10", Content: "内容10" },
{ ID: "content11", Content: "内容11" },
{ ID: "content12", Content: "内容12" },
{ ID: "content13", Content: "内容13" }
],
listBoxState: true
}
}
// 定义ref类型
Nav = createRef<HTMLDivElement>();
Content = createRef<HTMLDivElement>();
// 定义EveryHeight类型,这个是内容区每个子元素的高度
EveryHeight:number=0;
// 导航点击事件,void是没有返回值
NavClick(index: number): void {
this.setState({
Index: index,
listBoxState: false
})
let el = this.Content.current?.children[index] as HTMLDivElement;
this.EveryHeight = el.clientHeight;
this.ChangedNavScrollHeight(index);
if (this.Content.current) {
this.Content.current.scrollTop = el.offsetTop;
}
}
// 改变导航的滚动高
ChangedNavScrollHeight(index:number): void{
if (this.Nav.current) {
if(index<this.state.NavList.length/2){
this.Nav.current.scrollTop -= 300;
}
if (index >= this.state.NavList.length - this.state.NavList.length/2) {
this.Nav.current.scrollTop += 300;
}
}
}
// 监听内容区域滚动
ContentScroll(): void {
if (this.Content.current) {
for (let i: number = 0; i < this.Content.current?.children.length; i++) {
let el = this.Content.current.children[i] as HTMLDivElement;
if (this.state.listBoxState) {
if (this.Content.current.scrollTop >= el.offsetTop) {
this.setState({
Index: i
})
}
let index = this.state.Index;
this.ChangedNavScrollHeight(index);
}
// 开启内容区联动导航
if (this.Content.current.scrollTop === el.offsetTop) {
this.setState({
listBoxState: true
})
}
}
}
}
// 随机数
getRandom(min:number, max:number) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 开局设置
componentDidMount(): void{
for(var i=0;i<this.state.ContentList.length;i++){
if (this.Content.current) {
// 定义内容区每个子元素的高
let el = this.Content.current.children[i] as HTMLDivElement;
el.style.height=this.getRandom(150, 300) + "vh";
}
}
}
render() {
let NavList = this.state.NavList;
let ContentList = this.state.ContentList;
return (
<div className="linkage-wrap">
<div className="nav" ref={this.Nav}>
{NavList.map((item, index) => <div className={this.state.Index === index ? 'nav-list active' : 'nav-list'} onClick={this.NavClick.bind(this, index)} key={item.ID}>{item.Content}</div>)}
</div>
<div className="content" id='content' ref={this.Content} onScroll={this.ContentScroll.bind(this)}>
{ContentList.map((item) => <div className="content-list" key={item.ID}><div className="content-title">{item.Content}</div></div>)}
</div>
</div>
)
}
}
export default LinkAge;
index.less中
.linkage-wrap {
display: flex;
.nav {
height: 100vh;
overflow-y: scroll;
// scroll-behavior: smooth;
// -webkit-overflow-scrolling: touch;/* 解决ios滑动不流畅问题 */
font-size: 30px;
text-align: center;
color: #fff;
.nav-list {
height: 10vh;
line-height: 10vh;
width: 20vw;
background: rgb(46, 143, 253);
}
.nav-list.active {
background-color: rgb(219, 65, 246);
}
}
.content {
overflow-y: scroll;
height: 100vh;
scroll-behavior: smooth;
-webkit-overflow-scrolling: touch;
/* 解决ios滑动不流畅问题 */
transition: 0.3s ease-in all;
.content-list {
height: 100vh;
width: 80vw;
background-color: rgb(250, 62, 62);
font-size: 50px;
.content-title {
color: #333;
text-align: center;
height: 70px;
background: aqua;
position: sticky;
top: 0;
}
}
}
}
以上仅安卓可以用,如要ios使用,需要使用scrollTo方法,并且配合smoothscroll-polyfill。
下载smoothscroll-polyfill
npm install smoothscroll-polyfill --save
如果是ts项目的话还需要下载一个插件
npm i --save-dev @types/smoothscroll-polyfill
在当前页面的tsx文件中引入smoothscroll-polyfill
import smoothscroll from "smoothscroll-polyfill";
在改变scroll值的事件里写
smoothscroll.polyfill();
将上面的this.Content.current.scrollTop = el.offsetTop;改为
this.Content.current.scrollTo({top:el.offsetTop,behavior:"smooth"})