最近一直在做react-native相关的项目,根据需求做了一个上拉加载,下拉刷新的组件
组件内容
// 引入公用组件 Results 是一个显示各种状态的组件
import { Results } from './components/index.js'
class ReFlatList extends Component {
static propTypes = {
}
constructor(props) {
super(props)
this.state = {}
}
ListEmptyComponent = () => {
const { data } = this.props
if (data.error) {
return <Results type='error' width={size(500)} height={size(200)} />
}
if (data.pageNum == 0) {
return <Results type='reload' width={size(500)} height={size(200)} />
}
return <Results type='data' width={size(500)} height={size(200)} />
}
ListFooterComponent = () => {
const { data } = this.props
if (data.records.length > 0) {
if (data.records.length < data.total) {
return (
<View style={{ padding: 20, }}>
<ActivityIndicator text="正在加载" />
</View>
)
} else {
return (
<View style={{ padding: 20, }}>
<Text style={{ fontSize: 14, color: '#61676F', lineHeight: 16, textAlign: 'center' }}>到底了</Text>
</View>
)
}
}
return null
}
render() {
const { style, flatListStyle, progressBackgroundColor, data, ...props } = this.props
return (
<View style={{
flex: 1,
...style
}}>
<FlatList
style={{
flex: 1,
...flatListStyle
}}
keyExtractor={(item, index) => index.toString()}
ListEmptyComponent={this.ListEmptyComponent}
ListFooterComponent={this.ListFooterComponent}
onEndReachedThreshold={.0000001}
data={data.records}
{...props}
/>
</View>
)
}
}
使用方式
// antd 按需加载
import { Tabs, Toast, Portal } from '@ant-design/react-native';
// 引入 处理数据 所需文件
import { agentGoodsList } from './module/module.js'
// 引入公用组件
import { RnFlatList } from './components/index.js'
class AgentGoods extends Component {
constructor(props) {
super(props)
this.state = {
refreshing: false, // 刷新的的状态
loading: false, // 加载的状态
dataList: { // 存储接口返回的分页信息
total: 0,
size: 10,
current: 1,
pages: 1,
records: [] // 实际的数据
}
}
}
componentDidMount() {
// 进入页面后打开 loading 状态
this.loading = Toast.loading('加载中')
this.handleData({
current: 1,
})
}
// 处理数据请求
handleData(options) {
const { data, productId } = this.props
agentGoodsList({
productId,
size: 10,
...options
}).then(res => {
Portal.remove(this.loading)
this.setState({
dataList: {
...res.data,
records: this.state.dataList.records.concat(res.data.records)
}
})
}).catch(error => {
console.log(error, 11111)
})
}
onRefresh = () => {
this.setState({ refreshing: true });
const { data, productId } = this.props
const { dataList: { size } } = this.state
agentGoodsList({
current: 1,
productId,
size: 10,
}).then(res => {
this.setState({
dataList: res.data,
refreshing: false
})
}).catch(error => {
console.log(error, 11111)
})
}
onEndReached = () => {
const { dataList: { current, size, records, total } } = this.state
if (records.length < total) {
this.handleData({
current: current + 1,
})
}
}
onScroll = (e) => {
const { searchBackgroundColor } = this.state
if (e.nativeEvent.contentOffset.y >= size(366) - 44) {
this.setState({
searchBackgroundColor: '#e43130'
})
} else {
this.setState({
searchBackgroundColor: 'transparent'
})
}
}
render() {
const { refreshing, dataList } = this.state
const { integral } = this.props
return (
<View style={Style.container}>
<Status />
<RnFlatList
style={{
flex: 1,
backgroundColor: '#f0f2f5',
}}
columnWrapperStyle={{
paddingTop: 10,
}}
onScroll={this.onScroll}
refreshing={refreshing}
onRefresh={this.onRefresh}
onEndReached={this.onEndReached}
numColumns={2}
removeClippedSubviews={true}
data={dataList}
renderItem={({ item, index }) => {
const width = (ScreenWidth - 30) / 2
return (
<View style={{
width: width,
backgroundColor: '#fff',
// margin: 3
marginLeft: 10,
borderRadius: 10,
overflow: 'hidden'
// marginBottom: 3
}}>
<TouchableOpacity
onPress={() => {
Actions.goodDetails({ goodsId: item.id, productId: item.productId, })
}}
>
<CacheImage
resizeMod={"contain"}
style={{
width: width,
height: width,
}}
source={{ uri: `${pathHead}${item.goodsMainPic}` }}
defaultSource={background}
/>
</TouchableOpacity>
</View>
)
}}
/>
</View >
);
}
}