關(guān)于如何去制作一個(gè)上拉加載更多的組件

實(shí)現(xiàn)一個(gè)上拉加載更多,要考慮一下幾個(gè)問題

1.什么時(shí)候觸發(fā)加載
2.什么時(shí)候不觸發(fā)
3.具體怎么觸發(fā)

根據(jù)以上的幾條,可以設(shè)計(jì)這樣一個(gè)組件
1.什么時(shí)候觸發(fā),即滾動(dòng)到什么位置時(shí)開始觸發(fā),此處就需要一個(gè)閾值進(jìn)行判斷,我們叫它threshold,
2.什么時(shí)候不觸發(fā),也許大家說只要不達(dá)到閾值時(shí)就不觸發(fā),其實(shí)這樣是有偏差的,為什么呢,首先,滾動(dòng)時(shí),假如它的閾值設(shè)為50,那么小于等于50時(shí),就會(huì)觸發(fā),此時(shí)假如我們?cè)?-50之間隨意更改值,那么就會(huì)導(dǎo)致一直觸發(fā),這顯然不是我們想要的,一般不觸發(fā)可以這么來判斷,是否在加載數(shù)據(jù),是否已經(jīng)加載完所有的數(shù)據(jù),所以,我們需要兩個(gè)屬性去判斷isFetching,hasMore
3.怎么去觸發(fā),此時(shí)我們需要一個(gè)去觸發(fā)的action,這個(gè)action每次執(zhí)行之后,都會(huì)把pageIndex加1
總結(jié)一下,這個(gè)組件,我們需要一下幾個(gè)props
1.threshold;2.isFetching;3.hasMore;4.action
好了,有了以上幾條,接下來實(shí)操部分,首先,我們?cè)趺慈ニ愠鲈趺磘hreshold

getBoundingClientRect

此處我是用的getBoundingClientRect,這個(gè)方法在area中也用到了,我們來看看它的一些有用的值,left,right,top,bottom,width,height

1.left指元素的左邊距可視區(qū)域左邊的距離
2.right指元素的右邊距可視區(qū)域左邊的距離
3.top指元素的頂部距可視區(qū)域頂部的距離
4.bottom指元素的底部距可視區(qū)域頂部的距離

盜個(gè)圖,一目了然

image.png

然后我們只要每次去計(jì)算當(dāng)前列表的底部距離減去可視區(qū)域的高度小于我們的閾值時(shí),即觸發(fā)加載,其實(shí),講到這里,核心已經(jīng)差不多了,接下來看代碼吧

import React, { PureComponent } from 'react'
import ReactDOM from 'react-dom'
import PropTypes from 'prop-types'

import styles from './main.scss'

export default class Infinity extends PureComponent {
  state = {
    screenHeight: 0
  }
  render() {
    const { hasMore } = this.props
    return (
      <div>
        {this.props.children}
        <p className={styles.infinity}>{hasMore ? '加載中...' : '沒有更多了'}</p>
      </div>
    )
  }

  componentDidMount() {
    if (!this.props.children) {
      console.error('You must add a child!')
      return
    } else if (Object.prototype.toString.call(this.props.children) == '[object Array]' && this.props.children.length > 0) {
      console.error('Too many child')
      return
    }
    this.setState({
      screenHeight: window.innerHeight
    })
    window.addEventListener('scroll', this.scroll)
    this.pagination()
  }

  componentWillUnmount() {
    window.removeListener('scroll', this.scroll)
  }

  scroll = () => {
    const { panel, threshold } = this.props
    var rect = ReactDOM.findDOMNode(this).parentNode.getBoundingClientRect()
    let value = rect.bottom - this.state.screenHeight
    if (value < threshold) {
      this.pagination()
    }
  }

  pagination() {
    const { action, count, total, isFetching, hasMore } = this.props
    if (!isFetching && hasMore) {
      console.log('加載中')
      action()
    }
  }
}

Infinity.propTypes = {
  action: PropTypes.func, // 具體加載下一頁(yè)的事件
  threshold: PropTypes.number, // 加載的閾值
  isFetching: PropTypes.bool,
  hasMore: PropTypes.bool
}

Infinity.defaultProps = {
  action: () => {},
  threshold: 100,
  isFetching: false,
  hasMore: true
}

reducer中的處理

 state = Immutable.update(state, 'dataList', (dataList, payload) => dataList.concat(payload), action.payload)
 if (action.payload.length < state.pageSize) {
    state = Immutable.merge(state, { hasMore: false })
  }
 return Immutable.update(state, 'pageIndex', (pageIndex, step) => pageIndex + step, 1)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

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

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