react怎么实现上拉刷新

React上拉加载和下拉刷新

最近在做一个功能,就是上拉加载下一页,用的是react搭建前端视图,以下是我的做法和遇到的相关问题及解决办法:

案例一:回到顶部

class Home extends Component {
 consrcutor(props) {
    super(props);
    this.state={
        showScroll: false
    }
 }
 componentDidMount() {
    this.bindEvent();
  }
 
  componentWillUnmount() {
    window.removeEventListener("scoll", this.props.toggleTopShow);
  }
 
 
  bindEvent = () => {
    window.addEventListener("scroll", this.props.toggleTopShow);
  };
 
  toggleTopShow = () => {
      let showScroll = '';
      if (document.documentElement.scrollTop > 100) {
         showScroll = true;
      } else {
         showScroll = false;
      }
      
      this.setState({
          showScroll
      });
   }
  
  handleScrollTop = () => {
    window.scrollTo(0, 0);
  };
 
  
  render() {
    return (
      <div>
        {this.state.showScroll ? (
          <BackTop onClick={this.handleScrollTop}>
            <i className="iconfont ic-backtop">&#xe66a;</i>
          </BackTop>
        ) : null}
      </div>
    );
  }
}

案例二:上拉加载下一页

页面布局说明:页面:banner+nav+content(页面高度100%,除了banner+nav固定外,剩余高度都是content,其content在其区域内随着内容增多是可以滚动的)

根据上面说明知道:页面整体不滚动,只是页面的局部区域滚动,所以不能将scroll绑定到window上而是content上,如下:

class Pool extends PureComponent {
   constructor(props) {
    super(props);
    this.state = {
      PullLoadingTip: ""
    };
 
    this.isLock = true;
    this.PoolCon = React.createRef();
    this.ParentCon = React.createRef();
    this.scrollToBottom = this.scrollToBottom.bind(this);
  }
    
  componentDidMount() {
    this.ParentCon.current.addEventListener("scroll", this.scrollToBottom);
  }
 
  componentWillUnmount() {
    this.ParentCon.current.removeEventListener("scroll", this.scrollToBottom);
  }
 
  scrollToBottom(event) {
    event.stopPropagation();
 
    const parent = this.ParentCon.current; //event.target;
    let scrolltop = parent.scrollTop;  //content上部滚动出的高度
    let height = Zepto(parent).height();  //content的固定高度
    let scrollheight = this.PoolCon.current.scrollHeight;  //content内部内容的高度
   
    if (scrollheight <= scrolltop + height) {
      console.log("到底了");
      if (Math.ceil(this.TOTAL / LIMIT) >= this.PAGE + 1) { //有下一页才执行可以加载
        this.setState(
          {
            isShowPullLoading: true
          },
          () => {         
            if (this.isLock) {  //请求下一页过程中不在发送请求
              this.getData();
            }
          }
        );
      }
    }
  }
 
  getData(flag) {
    this.isLock = false
    //发送请求获取下一页数据,成功后this.isLock改为true
 }
    
  render() {
    return (
      <article className="content">
        <section ref={this.PoolCon}>
          {/*content列表内容*/}
          {this.state.isShowPullLoading ? (
            <p className="pull-loading">正在加载...</p>
          ) : (
            ""
          )}
        </section>
      </article>
    );
  }
}

问题:上面两个案例均在componentDidMount()中均绑定了scroll事件,但是绑定到window上功能正常,绑定到某个元素上只有第一次有效,之后就不会再出发scroll事件。

解决:在元素上直接添加onScroll事件,而不是在componentDidMount()中绑定。修改如下:

//去掉this.ParentCon = React.createRef();
 
//<article className="content" onScroll={this.scrollToBottom}>...</article>
 
//scrollToBottom中:const parent = event.target;

案例三:移动端上实现上拉加载下一页

网上有很多插件如iscroll、better-scroll、http://www.htmleaf.com/jQuery/jquery-tools/201905275664.html等,可以看看(未实测),但是我的需求要求不高,没有搜索react相关插件, 就是用上面的原理实现的。

移动端一般不监听scroll事件,所以将绑定的事件改为touchstart、touchmove、touchend

touchstart事件:当手指触摸屏幕时候触发,即使已经有一个手指放在屏幕上也会触发。

touchmove事件:当手指在屏幕上滑动的时候连续地触发。在这个事件发生期间,调用preventDefault()事件可以阻止滚动。

touchend事件:当手指从屏幕上离开的时候触发。

touchcancel事件:当系统停止跟踪触摸的时候触发。关于这个事件的确切出发时间,文档中并没有具体说明,咱们只能去猜测了。

问题:移动端touch相关事件是绑定到元素上,还是生命周期componentDidMount函数中?

实际测试onTouchmove、onTouchend直接绑定到元素上,可以触发,但是很难触发;绑定到componentDidMount上功能正常,即直接在componentDidMount中将touch相关事件绑定到content上。

//再把 this.PoolCon = React.createRef();加回来
 
// <article className="content" ref={this.ParentCon}>...</article>
 
 componentDidMount() {
    this.ParentCon.current.addEventListener("touchmove", () => this.scrollToBottom(event, 1), { passive: false });
    this.ParentCon.current.addEventListener("touchend", () => this.scrollToBottom(event, 2));
  }
 
  componentWillUnmount() {
    this.ParentCon.current.removeEventListener("touchmove", () => this.scrollToBottom(event, 1));
    this.ParentCon.current.removeEventListener("touchend", () => this.scrollToBottom(event, 2));
  }
 
 
  scrollToBottom(event, type) {
    event.stopPropagation();
 
    const parent = this.ParentCon.current; //event.target;
    let scrolltop = parent.scrollTop;
    let height = Zepto(parent).height();
    let scrollheight = this.PoolCon.current.scrollHeight;
 
    if (scrollheight <= scrolltop + height) {
      if (Math.ceil(this.TOTAL / LIMIT) >= this.PAGE + 1) {
        if (1 === type) {
          this.setState({
            PullLoadingTip: "释放立即加载..."
          });
        } else if (2 === type) {
          this.setState(
            {
              PullLoadingTip: "正在加载..."
            },
            () => {
              if (this.isLock) {
                this.getData();
              }
            }
          );
        }
      }
    }
  }

案例四:移动端实现下拉刷新

因为没有需求,所以不是react版本

<main class="parent">
        <p class="refreshText"></p>
        <ul id="refreshContainer">
            ...
            <li>111</li>
            ...
        </ul>
    </main>
window.onload = function(){
            //1.获取到列表的dom,刷新显示部分的dom,列表父容器的dom
            let container = document.querySelector('#refreshContainer');
 
            let refreshText = document.querySelector('.refreshText');
 
            let parent = document.querySelector('.parent');
 
 
            //2.定义一些需要常用的变量
            let startY = 0;//手指触摸最开始的Y坐标
 
            let endY = 0;//手指结束触摸时的Y坐标
 
            
            //3.给列表dom监听touchstart事件,得到起始位置的Y坐标
            parent.addEventListener('touchstart',function(e){
                startY = e.touches[0].pageY;
 
            });
 
            //4.给列表dom监听touchmove事件,当移动到一定程度需要显示上面的文字
            parent.addEventListener('touchmove',function (e) { 
 
                if(isTop() && (e.touches[0].pageY-startY) > 0){
 
                    console.log('下拉了');
 
                    refreshText.style.height = "50px";
 
                    parent.style.transform = "translateY(50px)";
 
                    parent.style.transition = "all ease 0.5s";
 
                    refreshText.innerHTML = "释放立即刷新...";
 
                }
 
            });
 
 
            //5.给列表dom监听touchend事件,此时说明用户已经松开了手指,应该进行异步操作了
            parent.addEventListener('touchend',function (e) { 
 
                if(isTop()){
 
                    refreshText.innerHTML = "正在刷新...";
 
                    setTimeout(function(){
 
                        parent.style.transform = "translateY(0)";
 
                        console.log('成功刷新');
 
                    },2000)
 
                }
 
                return;
 
            })
 
 
            function isTop(){
                var t = document.documentElement.scrollTop||document.body.scrollTop;
                return t === 0 ? true : false;
            }
        }

以上就是自己的做法,有问题可以留言,共同成长。

求告知好用的react相关组件库

更多相关技术文章,请访问HTML中文网

以上就是react怎么实现上拉刷新的详细内容,更多请关注html中文网其它相关文章!

赞(0) 打赏
未经允许不得转载:html中文网首页 » React 答疑

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

前端开发相关广告投放 更专业 更精准

联系我们

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏