app 下拉刷新和上拉加载是很常见的效果。
今天尝试用react 来实现下拉加载和点击按钮加载更多的效果
下面的代码是一个列表界面。将用下面代码来讲解怎么实现点击加载更多和下拉加载更多
List 页面
import React from 'react'
import PureRenderMixin from 'react-addons-pure-render-mixin'
import { getListData } from '../../../fetch/home/home'
import ListCompoent from '../../../components/List'
import LoadMore from '../../../components/LoadMore'
import './style.less'
class List extends React.Component {
constructor(props, context) {
super(props, context);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
this.state = {
data: [], //数据源
hasMore: false, //是否存在下一页
isLoadingMore: false,//是否正在加载
page: 0 //当前的页码
}
}
render() {
return (
<div>
<h2 className="home-list-title">猜你喜欢</h2>
{
this.state.data.length
? <ListCompoent data={this.state.data}/>
: <div>{/* 加载中... */}</div>
}
{
//这里如果有下一页。就显示由下一页的按钮。没有显示为空
this.state.hasMore
? <LoadMore isLoadingMore={this.state.isLoadingMore} loadMoreFn={this.loadMoreData.bind(this)}/>
: ''
}
</div>
)
}
componentDidMount() {
// 获取首页数据
this.loadFirstPageData()
}
// 获取首页数据
loadFirstPageData() {
const cityName = this.props.cityName
const result = getListData(cityName, 0)
this.resultHandle(result)
}
// 加载更多数据
loadMoreData() {
// 记录状态
this.setState({
isLoadingMore: true
})
const cityName = this.props.cityName
const page = this.state.page
const result = getListData(cityName, page)
this.resultHandle(result)
// 增加 page 技术
this.setState({
page: page + 1,
isLoadingMore: false
})
}
// 处理数据
resultHandle(result) {
result.then(res => {
return res.json()
}).then(json => {
const hasMore = json.hasMore
const data = json.data
this.setState({
hasMore: hasMore,
// 注意,这里讲最新获取的数据,拼接到原数据之后,使用 concat 函数
data: this.state.data.concat(data)
})
}).catch(ex => {
if (__DEV__) {
console.error('首页”猜你喜欢“获取数据报错, ', ex.message)
}
})
}
}
export default List
<LoadMore isLoadingMore={this.state.isLoadingMore} loadMoreFn={this.loadMoreData.bind(this)}/>
传但当前的状态(是否加载)给LoadMore组件 以及回调方法loadMoreFn
LoadMore
import React from 'react'
import PureRenderMixin from 'react-addons-pure-render-mixin'
import './style.less'
class LoadMore extends React.Component {
constructor(props, context) {
super(props, context);
this.shouldComponentUpdate = PureRenderMixin.shouldComponentUpdate.bind(this);
}
render() {
return (
<div className="load-more" ref="wrapper">
{
//如果正在加载中就显示加载中。不是就显示加载更多的按钮
this.props.isLoadingMore
? <span>加载中...</span>
: <span onClick={this.loadMoreHandle.bind(this)}>加载更多</span>
}
</div>
)
}
loadMoreHandle() {
// 执行传输过来的
this.props.loadMoreFn();
}
//下拉加载更多的方法
componentDidMount() {
// 使用滚动时自动加载更多
const loadMoreFn = this.props.loadMoreFn
const wrapper = this.refs.wrapper
let timeoutId
function callback() {
const top = wrapper.getBoundingClientRect().top
const windowHeight = window.screen.height
if (top && top < windowHeight) {
// 证明 wrapper 已经被滚动到暴露在页面可视范围之内了
loadMoreFn()
}
}
window.addEventListener('scroll', function () {
if (this.props.isLoadingMore) {
return
}
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(callback, 50)
}.bind(this), false);
}
}
export default LoadMore
这样点击加载更多
的时候就调用传多来的函数loadMoreFn
.对应的就会执行loadMoreData()
这个函数去加载更多的数据
下拉加载
原理就是监听屏幕的滚动。判断当前加载更多
按钮是否已经出现在页面上。如果出现就直接加载更多。这里要做一个节流。就是当50ms 判断有没有第二次触发滚动,如果没有执行callback
//下拉加载更多的方法
componentDidMount() {
// 使用滚动时自动加载更多
const loadMoreFn = this.props.loadMoreFn
const wrapper = this.refs.wrapper
let timeoutId
function callback() {
//获取到按钮离顶部的距离
const top = wrapper.getBoundingClientRect().top
const windowHeight = window.screen.height
if (top && top < windowHeight) {
// 证明 wrapper 已经被滚动到暴露在页面可视范围之内了
loadMoreFn()
}
}
window.addEventListener('scroll', function () {
if (this.props.isLoadingMore) {
return
}
if (timeoutId) {
clearTimeout(timeoutId)
}
//如果在50ms 以内没有执行scroll 就会执行callBack,如果有下一次滚动,定时器就会被清空
timeoutId = setTimeout(callback, 50)
}.bind(this), false);
}
网友评论