终于要开始编写业务代码了,今天将组合前面9天学习的内容来制作一个「最热」功能.
View层page/PopularTab.js
import React, { Component } from "react";
import { FlatList, View, Text, StyleSheet, Button, RefreshControl, ActivityIndicator ,DeviceInfo} from "react-native";
import PopularItem from "../common/PopularItem";
import { connect } from "react-redux";
import actions from "../action/index";
import Toast, { DURATION } from 'react-native-easy-toast';
// import NavigationBar from "../common/NavigationBar";
const THEME_COLOR = "red";
const URL = 'https://api.github.com/search/repositories?q=';
const QUERY_STR = '&sort=stars';
const PAGE_SIZE = 10;
class PopularTab extends Component {
constructor(props) {
super(props);
const { tabLabel } = this.props;
this.storeName = tabLabel;
this.canLoadMore = false;//防止在初始化时就执行一次loadmore
}
genFetchUrl = (storeName) => {
return `${URL}${storeName}${QUERY_STR}`
}
loadData = (more) => {
const { onLoadPopularData, onLoadMorePopular, popular } = this.props;
const url = this.genFetchUrl(this.storeName);
const popularData = popular[this.storeName];
const that = this;
if (more) {
onLoadMorePopular(this.storeName, url, PAGE_SIZE, popularData.pageIndex + 1, popularData.dataArray, function () {
that.refs.toast.show('没有更多了');
});
}
else {
onLoadPopularData(this.storeName, url, PAGE_SIZE, function () {
that.refs.toast.show('已是最新');
});
}
}
componentDidMount() {
this.loadData();
}
renderItem = (data) => {
const item = data.item;
return <PopularItem item={item} />
}
//到达底部后触发
onEndReachedHandler = () => {
// console.log("没有更多了");
this.loadData(true);
}
EndComponent = (props) => {
return <View style={styles.footerComponent}>
<ActivityIndicator style={styles.activity}
animating={true}
size={"large"}
color={THEME_COLOR}
></ActivityIndicator>
<Text>正在加载更多</Text>
</View>;
}
render() {
const { popular } = this.props;
let store = popular[this.storeName];//动态获取state
let { EndComponent, canLoadMore } = this;
if (!store) {
store = {
projectModes: [],
isLoading: true,
isLoadingMore: false
};
}
return (
<View style={styles.container}>
{
store && (!store.projectModes || store.projectModes.length == 0) ?
<View style={styles.topActivity}>
<ActivityIndicator style={styles.activity}
animating={true}
size={"large"}
// style={{fontSize:30}}
color={THEME_COLOR}
/>
<Text style={{ color: THEME_COLOR }}>loading</Text>
</View>
:
<FlatList
data={store.projectModes}
renderItem={data => this.renderItem(data)}
keyExtractor={item => "" + item.id}
refreshControl={
<RefreshControl
title={"loading"}
titleColor={THEME_COLOR}
colors={[THEME_COLOR]}
refreshing={store.isLoading}
tintColor={THEME_COLOR}
// size={"large"}
onRefresh={() => {
this.loadData();
}}
style={{ fontSize: 30 }}
/>
}
ListFooterComponent={store.isLoadingMore ? <EndComponent /> : ""}
//到达底部
onEndReached={
() => {
setTimeout(() => {
if (!this.canLoadMore) return;
this.onEndReachedHandler()
this.canLoadMore = false;
console.log("---------------------到达底部---------------------");
}, 100);
}
}
onEndReachedThreshold={0.5}
onMomentumScrollBegin={() => {
this.canLoadMore = true;
console.log("---------------------开启loadMore---------------------");
}}
/>
}
<Toast ref="toast"
style={{ backgroundColor: 'black' }}
position='top'
positionValue={200}
fadeInDuration={750}
fadeOutDuration={1000}
opacity={0.8}
textStyle={{ color: 'white' }}
/>
</View>
);
}
}
const styles = StyleSheet.create({
topActivity: {
marginVertical: 20,
justifyContent: "center",
alignItems: "center",
},
container: {
flex: 1,
},
footerComponent: {
flex: 1,
justifyContent: "center",
alignItems: "center",
marginTop: 25
},
activity: {
marginBottom: 5
}
});
const mapStateToProps = state => ({
popular: state.popular
});
const mapDispatchToProps = dispatch => ({
onLoadPopularData: (storeName, url, pageSize, callback) => dispatch(actions.onLoadPopularData(storeName, url, pageSize, callback)),
onLoadMorePopular: (storeName, url, pageSize, pageIndex, dataArray, callback) => dispatch(actions.onLoadMorePopular(storeName, url, pageSize, pageIndex, dataArray, callback))
});
const PoplarTabPage = connect(mapStateToProps, mapDispatchToProps)(PopularTab);
export default PoplarTabPage;
这里使用了:
遇到的问题:
ActivityIndicator
模拟第一次loading动画的方式解决了这个问题,不过并不完美,头次动画由于和后续动画尺寸上无法一致,会导致比较难看的问题,哪位有解决的方案请私信本人.下面是我的处理方式: <View style={styles.container}>
{
store && (!store.projectModes || store.projectModes.length == 0) ?
<View style={styles.topActivity}>
<ActivityIndicator style={styles.activity}
animating={true}
size={"large"}
// style={{fontSize:30}}
color={THEME_COLOR}
/>
<Text style={{ color: THEME_COLOR }}>loading</Text>
</View>
:
<FlatList
data={store.projectModes}
renderItem={data => this.renderItem(data)}
keyExtractor={item => "" + item.id}
refreshControl={
<RefreshControl
title={"loading"}
titleColor={THEME_COLOR}
colors={[THEME_COLOR]}
refreshing={store.isLoading}
tintColor={THEME_COLOR}
// size={"large"}
onRefresh={() => {
this.loadData();
}}
style={{ fontSize: 30 }}
/>
}
ListFooterComponent={store.isLoadingMore ? <EndComponent /> : ""}
//到达底部
onEndReached={
() => {
setTimeout(() => {
if (!this.canLoadMore) return;
this.onEndReachedHandler()
this.canLoadMore = false;
console.log("---------------------到达底部---------------------");
}, 100);
}
}
onEndReachedThreshold={0.5}
onMomentumScrollBegin={() => {
this.canLoadMore = true;
console.log("---------------------开启loadMore---------------------");
}}
/>
}
<Toast ref="toast"
style={{ backgroundColor: 'black' }}
position='top'
positionValue={200}
fadeInDuration={750}
fadeOutDuration={1000}
opacity={0.8}
textStyle={{ color: 'white' }}
/>
</View>
这篇文章由于记录的是业务代码的编写情况,所以没写太多的知识点,但是说真的看教程和实际写还是很不同的,今天我是决定看了基本思路就完全自己实现这个“最热”功能,真的是收获良多,而这些收获是没法说出来的:比如调试的方式,调试工具的配置,代码的优化等等,建议大家看教程的时候多动手多记录.