react 数据懒加载-滚动实现

使用场景

项目中碰到这样一种情况,后台接口数据由于太多没法一次传输,因此希望前端在调接口时设置pageIdx和pageSize字段实现懒加载。前端页面上边一部分为选项栏下面一部分为滚动区域,大致的html结构简单抽象如下:

<div className='wrapper'>
    <div className='header'></div>
    <div className='scroll-body'></div>
</div>

简单的上下布局,外层为wrapper封装类,里面分上下两层,上面header类固定,下面就是要实现滚动懒加载的scroll-body区域。

涉及的问题列表:

  1. 如何计算scroll-body区域的高度来让scroll区域填充完除了header外的剩余部分,采用的css为:
.scroll-body {
    overflow: auto; //设置scroll overflow
    -webkit-overflow-scrolling: touch; // 优化移动端滑动体验
}
  1. 如何判断页面滚动到底部?

解决方案

  1. 针对第一个问题,可行的办法有两个:

方案1

在componentDidMount后获取对应header的高度,然后用window.innerHeight减去渲染后的header ref高度,公式如下:

scrollHeight = window.innerHeight - this.header.clientHeight

在render方法中需要给header提前设置ref,并且需要新增一个state来控制,具体代码如下:

class Test extents Component{
    constructor(props){
        super(props);
        this.state = {
            scrollHeight: 0
        }
    }

    componentDidMount(){
        this.setState({
            scrollHeight: window.innerHeight - this.header.clientHeight
        })
    }

    render(){
        const {scrollHeight} = this.state;

        return (
            <div className='wrapper'>
                <div className='header' ref={ref=>this.header}></div>
                <div className='scroll-body' style={{height: scrollHeight}}></div>
            </div>
        )
    }
}

上述方案的优点是可以动态设置高度,减少响应的计算,缺点是必须在render渲染后才能设置。

方案2

提前计算高度,这里有个限制,比如现在移动端中设置header的高度为2rem,需要从rem转换到像素,而获取当前设备的html的fontSize的方法可用的还比较有限,比如document.documentElement.style.fontSize,返回的数值为字符串比如’165px’,还没法直接拿来用,如果没有设置的话返回的是空串”。需要做个处理,具体依据项目中而定。


  1. 如果判断滚动到底部,触发接口调取下一页的数据?
    react有不少现成的实现滚动的组件,在google上搜索会出来很多。不过就实现来说也是比较简单的,这里给出一种可行的方案:
class Test extents Component{
    constructor(props){
        super(props);
        this.state = {
            scrollHeight: 0,
            hasMore: true// 判断接口是否还有数据,通过接口设置
            dataList:[], // 数据列表
        }
    }

    componentDidMount(){
        this.setState({
            scrollHeight: window.innerHeight - this.header.clientHeight
        })
    }

    // 处理滚动监听
    handleScroll(){
        const {hasMore} = this.state;
        if(!hasMore){
            return;
        }
        //下面是判断页面滚动到底部的逻辑
        if(this.scrollDom.scrollTop + this.scrollDom.clientHeight >= this.scrollDom.scrollHeight){
            this.fetchData()
        }
    }

    fetchData(){
        // 接口调用数据字段
        //传入的参数包括但不限于:pageIndex, pageSize。。。
        // 获取后更新的数据包括但不限于:dataList,hasMore。。。
    }

    render(){
        const {scrollHeight} = this.state;

        return (
            <div className='wrapper'>
                <div className='header' ref={ref=>this.header}></div>
                <div
                ref={body=>this.scrollDom = body} 
                className='scroll-body' 
                style={{height: scrollHeight}}
                onScroll={this.handleScroll.bind(this)}
                >
                </div>
            </div>
        )
    }
}

猜你喜欢

转载自blog.csdn.net/u011077672/article/details/81252347