React 實現(xiàn)加載更多

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);
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 178,725評論 25 709
  • ie8中遇到的兼容問題以及解決方案 一.CSS3 1.可以通過在css中引入pie.htc,處理兼容問題(可處理的...
    逍遙g閱讀 326評論 0 0

友情鏈接更多精彩內(nèi)容