资讯专栏INFORMATION COLUMN

React-实现上拉加载更多

avwu / 3190人阅读

摘要:光判断滑到最底部是不够的,首先需要知道用户现在的操作,是点击还是滑动向上向下向左向右这里受到了原生判断手指滑动方向的启发。最近想找图片缩放的插件,感觉也跟触摸事件有关,可以研究一下。

1. 写在前面
我最开始纠结当用户滑动时onTouchMove事件会不停的执行去调接口,于是我侥幸的想只用onTouchEnd事件去判
断用户是否滑到最底部,但是这种方法应用到项目中才发现点击的时候也会触发onTouchEnd,实际应用并不理想。
光判断滑到最底部是不够的,首先需要知道用户现在的操作,是点击还是滑动(向上、向下、向左、向右),这里
受到了[原生js判断手指滑动方向][1]的启发。

2. demo
class demo Component {
     constructor(props) {
        super(props);
        this.state = {
            finished: false,//是否全部加载完毕
            isFoot: true,   //阻止用户频繁上拉调接口
        }
        this._page = 1;              //分页页码                           
        this.val = "";               //搜索框的值
        this._page_size = 5;         //每页显示个数 
        this.startx;                 //触摸起始点x轴坐标
        this.starty;                 //触摸起始点y轴坐标 
    }
    //接触屏幕
    touchStart(e) {
        this.startx = e.touches[0].pageX;
        this.starty = e.touches[0].pageY;
    }
    //离开屏幕([e.changedTouches][2])
    touchEnd(e) {
        let endx, endy;
        endx = e.changedTouches[0].pageX;
        endy = e.changedTouches[0].pageY;
        let direction = this.getDirection(this.startx, this.starty, endx, endy);
        switch (direction) {
            case 0:
                console.log("未滑动!");
                break;
            case 1:
                console.log("向上!");
                this.loadData();
                break;
            case 2:
                console.log("向下!");
                break;
            case 3:
                console.log("向左!");
                break;
            case 4:
                console.log("向右!");
                break;
            default:
        }
    }
    //触摸点和离开点连线与[x轴角度][3]
    getAngle(angx,angy) {
        return Math.atan2(angy, angx) * 180 / Math.PI;
    }
    //根据接触和离开判断方向 1向上 2向下 3向左 4向右 0未发生滑动([Math.abs][4])
    getDirection(startx, starty, endx, endy) {
        let angx = endx - startx;
        let angy = endy - starty;
        let result = 0;

         //如果滑动距离太短
         if (Math.abs(angx) < 2 && Math.abs(angy) < 2) {
            return result;
        }
        let angle = this.getAngle(angx, angy);
        if (angle >= -135 && angle <= -45) {
            result = 1;
        } else if (angle > 45 && angle < 135) {
            result = 2;
        } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
            result = 3;
        } else if (angle >= -45 && angle <= 45) {
            result = 4;
        }
 
        return result;
    }
    //**向上滑动时(在这里才真正的判断是否到最底部)**
    loadData() {
        console.log("数据的高-------------------------", this.refs.onPullUp.clientHeight);
        console.log("滚动的高------------------------", document.documentElement.scrollTop);
        console.log("滚动的高------------------------", document.body.scrollTop);
        console.log("屏幕的高------------------------", document.documentElement.clientHeight);
        let { meActs } = this.props;
        let dataHeight = this.refs.onPullUp.clientHeight;
        let scrollHeight = document.body.scrollTop || document.documentElement.scrollTop;
        let screenHeight = document.documentElement.clientHeight;
        const h = 10;//自定义距离底部多少时concat数据
        if (dataHeight - scrollHeight - h < screenHeight && this.state.isFoot) {
            this.setState({
                isFoot: false,
            });
            console.log("应该只显示1次");
            let params = {
                value: this.val,
                page_index: this._page,
                page_size: this._page_size,
            }
            meActs.getRecentReadList(this.accessKey, this.accessID, params).then((res) => {
                if (res.data.code === 10000 && res.data.data.list.length > 0) {
                    this.setState({
                        isFoot: true,
                    });
                    this._page++;
                }
                //数据加载完毕
                if (res.data.code === 10000 && res.data.data.list.length == 0) {
                    this.setState({
                        finished: true,
                    })
                }
            });
        }
    }
    
    render() {
        return(
             
{listItems}
{ this.state.finished ? 我是有底线的 : recentReadList.list.length > 0 ? this.state.isFoot ? 上拉加载更多 : : 暂无信息 }
) } }
3. 兼容性
微信端ios 安卓暂时还未发现任何异常(已上线的项目) 

4. 结语
移动端触摸事件的用处远不止如此,这次是因为antd自带的上拉加载插件在自身项目中应用太复杂所以决定自己
写一个满足自身项目需求的代码少兼容性还看得过去的就行。最近想找react图片缩放的插件,感觉也跟触摸事件
有关,可以研究一下。

**

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/92302.html

相关文章

  • 复杂type页面封装库,支持多种状态切换和下拉刷新拉加

    摘要:支持复杂页面,例如添加自定义头部和底部布局,支持横向滑动,还可以支持粘贴头部类似微信好友分组,支持不规则瀑布流效果,支持侧滑删除功能。十分方便实现复杂的布局页面,结构上层次分明,便于维护。 目录介绍 1.复杂页面库介绍 2.本库优势亮点 2.1 支持多种状态切换管理 2.2 支持添加多个header和footer 2.3 支持侧滑功能和拖拽移动 2.4 其他亮点介绍 3.如...

    Karrdy 评论0 收藏0
  • RecyclerView封装库和综合案例【包含25篇博客】

    摘要:支持复杂页面,例如添加自定义头部和底部布局,支持横向滑动,还可以支持粘贴头部类似微信好友分组,支持不规则瀑布流效果,支持侧滑删除功能。支持粘贴头部的需求效果,这种效果类似微信好友分组的那种功能界面。 目录介绍 1.复杂页面库介绍 2.本库优势亮点 2.1 支持多种状态切换管理 2.2 支持添加多个header和footer 2.3 支持侧滑功能和拖拽移动 2.4 其他亮点介绍 ...

    silenceboy 评论0 收藏0
  • webpack+vue+mint-ui 实现拉加更多(Loadmore组件)

    摘要:因为业务的需要界面需要实现分页的功能,所以我就研究了一下如何利用自带的组件实现上拉加载更多功能。代码如下上拉加载更多初始化方法如下下面便是上拉加载更多的方法这样就大功告成啦 因为业务的需要界面需要实现分页的功能,所以我就研究了一下如何利用mint-ui自带的loadmore组件实现上拉加载更多功能。 首先在文件中引入组件 import {Indicator, Loadmore} f...

    LiuZh 评论0 收藏0
  • Vue+Better-Scroll 实现多Tab拉加更多实例

    摘要:本场是讲一个基于实现多切换上拉加载更多的实例,像这种多切换加载更多的场景,不管在端还是移动端都还挺常见的,比如商城类,订单中心等。通过学习本项目,你也可以做出多切换上拉加载更多的效果,而不必到处找别人的例子。 本场 Chat 是讲一个基于 Vue+Better-Scroll 实现多 Tab 切换上拉加载更多的实例,像这种多 Tab 切换加载更多的场景,不管在 PC 端还是移动端都还挺常...

    wuyangchun 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<