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"></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怎么实现上拉刷新的详细内容,更多请关注易知道|edz.cc其它相关文章!