最近用react做了一个手机端,可以说了解了很多以前没有接触的东西,其中在项目中实现滑动分页让我印象颇为深刻。首先,我们要知道这个功能需要用到哪些准备知识。
一、预备阶段
我的想法很简单,就是计算每次加载的最后一条距离项目footer垂直方向上的距离,从而知道什么时候需要将当前页面+1并且向后端发送请求,将重新获得的数据加到上一次获取数据的后面。首先,我们要知道在React中滑动调用的事件叫“onScroll”;其次我们知道react中使用虚拟DOM是叫this.refs[ref名],获取这个ref定位的方法叫getBoundingClientRect(),由于现在手机的高度不一,所以我选择的是获取底部的距离,假设这个ref="footer",则该footer和底部的距离就是
let footerY = parseInt(this.refs.footer.getBoundingClientRect().bottom)
二、实现阶段
有了这些背景知识,我们就可以去编写代码了,我先把大致的代码放上去,然后逐步解析。
class myComponents extends Component {
constructor(props) {
super(props)
this.state = {
data: [],
loading: false,
currentPage: 1,
pageSize: 10,
count: 0
}
}
componentWillMount() {
this.getData()
}
this.getData() { // 向后端发送Ajax请求并获取到count和data,这部分为伪代码
this.setState({loading: true})
// 发送请求
this.setState(prevState => { //请求回调里的
count: 32,
loading: false,
data: [...prevState.data, ...data]
})
}
touchMove() { // 滑动事件调用方法
let pageSize = this.state.pageSize
let currentPage = this.state.currentPage
let data = this.state.data
let lastY = parseInt(this.refs['item' + (data.length - 1)].getBoundingClientRect().bottom)
let footerY = parseInt(this.refs.footer.getBoundingClientRect().bottom)
if ( !this.state.loading && lastY - footerY < 0 && data.length >= pageSize *(currentPage - 1) && data.length <= pageSize * currentPage && applicant.length < this.state.count) {
this.setState(prevState => ({
currentPage: prevState.currentPage + 1
}),
() => {
this.getData()
})
}
render() {
<div>
{ this.data.map((item, index) => {
return <div key={index} ref={'item' + index}
onTouchMove={() =>this.touchMove()}
>{item.name}</div>
})
}
<Footer ref="footer" />
<div>
}
}
我先在state初始化时定一个初始页码currentPage为“1”,pagesize定为10,loading是为了达到可以加载数据的时候,只执行一次,如果多次调用后台接口会在data中push多次某一页的内容,这肯定是我们不想要的。然后下滑时调用touchMove方法,计算我最后一条数据(第一页就是index=9,第二页就是index=19,以此类推)与footer的bottom距离的插值,当达到某个值时,调用接口获取后端数据,将其放到state.data的最后,currentPage+1,这样可以计算data更新后最后一条与footer的bottom的距离,最后当后端给我们的总条数count与我自己的数据相等时,不再调用请求。