160 lines
4.6 KiB
TypeScript
160 lines
4.6 KiB
TypeScript
import { ScrollView, View } from '@tarojs/components'
|
||
import type { ReactNode } from 'react'
|
||
import React, { memo, useMemo, useState } from 'react'
|
||
import LoadingCard from '../loadingCard'
|
||
import style from './index.module.scss'
|
||
import DotLoading from '@/components/dotLoading'
|
||
import Empty from '@/components/empty'
|
||
import { SEARCH_EMPTY_IMAGE } from '@/common/constant'
|
||
|
||
export type StatusParam = 0 | 1 | 2 | 3
|
||
|
||
interface Params {
|
||
styleObj?: React.CSSProperties
|
||
selfonScrollToLower?: () => void
|
||
enableLoadMoreStatus?: boolean
|
||
safeAreaInsetBottom?: boolean
|
||
moreStatus?: boolean
|
||
statusMore?: StatusParam // 0:数据从无到有加载数据,1,没有任何数据, 2:下拉加载,3:下拉没有数据
|
||
children?: ReactNode
|
||
lowerThresholdNum?: number
|
||
selfOnScrollToUpper?: () => void
|
||
selfOnScroll?: (val: any) => void
|
||
selfOnRefresherPulling?: () => void
|
||
selfOnRefresherRefresh?: () => void
|
||
selfOnRefresherRestore?: () => void
|
||
selfOnRefresherAbort?: () => void
|
||
paddingBottom?: number
|
||
refresherTriggered?: boolean
|
||
refresherEnabled?: boolean
|
||
enableBackToTop?: boolean
|
||
emptySlot?: React.ReactNode
|
||
moreText?: string
|
||
loadingText?: string
|
||
noMoreText?: string
|
||
}
|
||
const InfiniteScroll = ({
|
||
styleObj,
|
||
selfonScrollToLower,
|
||
selfOnScrollToUpper,
|
||
selfOnScroll,
|
||
selfOnRefresherPulling,
|
||
selfOnRefresherRefresh,
|
||
selfOnRefresherRestore,
|
||
selfOnRefresherAbort,
|
||
safeAreaInsetBottom = true,
|
||
enableLoadMoreStatus = true,
|
||
children,
|
||
lowerThresholdNum = 5,
|
||
paddingBottom = 0,
|
||
refresherTriggered = false,
|
||
refresherEnabled = false,
|
||
moreStatus = true,
|
||
statusMore = 0,
|
||
enableBackToTop = true,
|
||
emptySlot,
|
||
}: Params) => {
|
||
const scrollToLower = () => {
|
||
selfonScrollToLower?.()
|
||
}
|
||
const scrollToUpper = () => {
|
||
selfOnScrollToUpper?.()
|
||
}
|
||
const scroll = (e) => {
|
||
selfOnScroll?.(e)
|
||
}
|
||
const refresherPulling = () => {
|
||
selfOnRefresherPulling?.()
|
||
}
|
||
const refresherRefresh = () => {
|
||
selfOnRefresherRefresh?.()
|
||
}
|
||
const refresherRestore = () => {
|
||
selfOnRefresherRestore?.()
|
||
}
|
||
const refresherAbort = () => {
|
||
selfOnRefresherAbort?.()
|
||
}
|
||
|
||
// 返回顶部
|
||
const scrollTop = useMemo(() => {
|
||
if (statusMore == 0) {
|
||
return 0.1
|
||
}
|
||
}, [statusMore])
|
||
|
||
const component = () => {
|
||
if (enableLoadMoreStatus) {
|
||
if (!moreStatus) {
|
||
return (
|
||
<View style={{ paddingBottom: `${paddingBottom}rpx` }} className={style.scrollViewCon}>
|
||
{children}
|
||
</View>
|
||
)
|
||
}
|
||
else {
|
||
return (
|
||
<>
|
||
{(statusMore == 2 || statusMore == 3) && (
|
||
<View style={{ paddingBottom: `${paddingBottom}rpx` }} className={style.scrollViewCon}>
|
||
{children}
|
||
<View className={style.infinite_scroll}>
|
||
{statusMore == 2
|
||
? (
|
||
<View className={style.loading_more}>
|
||
加载中
|
||
<DotLoading />
|
||
</View>
|
||
)
|
||
: (
|
||
<View className={style.noMore}>没有更多数据了</View>
|
||
)}
|
||
</View>
|
||
</View>
|
||
)}
|
||
{statusMore == 0 && <LoadingCard />}
|
||
{statusMore == 1 && (emptySlot || <Empty picUrl={SEARCH_EMPTY_IMAGE} text="暂无数据" />)}
|
||
</>
|
||
)
|
||
}
|
||
}
|
||
else {
|
||
return (
|
||
<View style={{ paddingBottom: `${paddingBottom}rpx` }} className={style.scrollViewCon}>
|
||
{children}
|
||
</View>
|
||
)
|
||
}
|
||
}
|
||
|
||
return (
|
||
<>
|
||
<ScrollView
|
||
id="infiniteScroll"
|
||
style={styleObj}
|
||
className={style.scroll_main}
|
||
scrollY
|
||
onScrollToLower={() => scrollToLower()}
|
||
onScrollToUpper={() => scrollToUpper()}
|
||
onScroll={e => scroll(e)}
|
||
lowerThreshold={lowerThresholdNum}
|
||
refresherEnabled={refresherEnabled}
|
||
refresherTriggered={refresherTriggered}
|
||
onRefresherPulling={() => refresherPulling()}
|
||
onRefresherRefresh={() => refresherRefresh()}
|
||
onRefresherRestore={() => refresherRestore()}
|
||
onRefresherAbort={() => refresherAbort()}
|
||
refresherBackground="#F8F8F8"
|
||
enableBackToTop={enableBackToTop}
|
||
scrollTop={scrollTop}
|
||
>
|
||
{component()}
|
||
{safeAreaInsetBottom && <View className="common_safe_area_y"></View>}
|
||
</ScrollView>
|
||
</>
|
||
)
|
||
}
|
||
export default memo(
|
||
InfiniteScroll,
|
||
)
|