app 下拉刷新和上拉加載是很常見的效果。
今天嘗試用react 來實現(xiàn)下拉加載和點擊按鈕加載更多的效果
下面的代碼是一個列表界面。將用下面代碼來講解怎么實現(xiàn)點擊加載更多和下拉加載更多
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: [], //數(shù)據(jù)源
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() {
// 獲取首頁數(shù)據(jù)
this.loadFirstPageData()
}
// 獲取首頁數(shù)據(jù)
loadFirstPageData() {
const cityName = this.props.cityName
const result = getListData(cityName, 0)
this.resultHandle(result)
}
// 加載更多數(shù)據(jù)
loadMoreData() {
// 記錄狀態(tài)
this.setState({
isLoadingMore: true
})
const cityName = this.props.cityName
const page = this.state.page
const result = getListData(cityName, page)
this.resultHandle(result)
// 增加 page 技術(shù)
this.setState({
page: page + 1,
isLoadingMore: false
})
}
// 處理數(shù)據(jù)
resultHandle(result) {
result.then(res => {
return res.json()
}).then(json => {
const hasMore = json.hasMore
const data = json.data
this.setState({
hasMore: hasMore,
// 注意,這里講最新獲取的數(shù)據(jù),拼接到原數(shù)據(jù)之后,使用 concat 函數(shù)
data: this.state.data.concat(data)
})
}).catch(ex => {
if (__DEV__) {
console.error('首頁”猜你喜歡“獲取數(shù)據(jù)報錯, ', ex.message)
}
})
}
}
export default List
<LoadMore isLoadingMore={this.state.isLoadingMore} loadMoreFn={this.loadMoreData.bind(this)}/>
傳但當前的狀態(tài)(是否加載)給LoadMore組件 以及回調(diào)方法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() {
// 執(zhí)行傳輸過來的
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 已經(jīng)被滾動到暴露在頁面可視范圍之內(nèi)了
loadMoreFn()
}
}
window.addEventListener('scroll', function () {
if (this.props.isLoadingMore) {
return
}
if (timeoutId) {
clearTimeout(timeoutId)
}
timeoutId = setTimeout(callback, 50)
}.bind(this), false);
}
}
export default LoadMore
這樣點擊加載更多的時候就調(diào)用傳多來的函數(shù)loadMoreFn.對應(yīng)的就會執(zhí)行loadMoreData()這個函數(shù)去加載更多的數(shù)據(jù)
下拉加載
原理就是監(jiān)聽屏幕的滾動。判斷當前加載更多按鈕是否已經(jīng)出現(xiàn)在頁面上。如果出現(xiàn)就直接加載更多。這里要做一個節(jié)流。就是當50ms 判斷有沒有第二次觸發(fā)滾動,如果沒有執(zhí)行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 已經(jīng)被滾動到暴露在頁面可視范圍之內(nèi)了
loadMoreFn()
}
}
window.addEventListener('scroll', function () {
if (this.props.isLoadingMore) {
return
}
if (timeoutId) {
clearTimeout(timeoutId)
}
//如果在50ms 以內(nèi)沒有執(zhí)行scroll 就會執(zhí)行callBack,如果有下一次滾動,定時器就會被清空
timeoutId = setTimeout(callback, 50)
}.bind(this), false);
}