在本节中,我们将编写首页的列表组件,并实现列表项的点击事件处理和性能优化。
一、创建 Model
在 models/home.ts 中添加以下内容:
-
声明接口地址:
const CHANNEL_URL = '/mock/11/bear/channel'; -
定义
IChannel接口:export interface IChannel { id: string; image: string; title: string; played: number; playing: number; remark: string; } -
在
HomeState中定义channelList属性:export interface HomeModelState { carousels: ICarousel[]; guess: IGuess[]; channelList: IChannel[]; } -
在
effects中定义请求频道列表数据:effects: { *fetchChannelList(_, { call, put }) { const { data } = yield call(axios.get, CHANNEL_URL); yield put({ type: 'setState', payload: { channelList: data.results, }, }); }, },
二、创建列表组件
在 pages/Home/index.tsx 中编写列表组件:
1. 编写 ChannelItem 组件
import React from 'react';
import { View, Text, Image, StyleSheet, TouchableOpacity } from 'react-native';
import Icon from '@/assets/iconfont/index';
import { IChannel } from '@/models/home';
interface IProps {
item: IChannel;
onPress: (item: IChannel) => void;
}
class ChannelItem extends React.PureComponent<IProps> {
onPress = () => {
const { item, onPress } = this.props;
onPress(item);
};
render() {
const { item } = this.props;
return (
<TouchableOpacity onPress={this.onPress} style={styles.container}>
<View style={styles.item}>
<Image source={{ uri: item.image }} style={styles.image} />
<View style={styles.rightView}>
<Text style={styles.titleText} numberOfLines={2}>
{item.title}
</Text>
<Text style={styles.remarkText} numberOfLines={2}>
{item.remark}
</Text>
<View style={styles.bottomView}>
<View style={styles.playedView}>
<Icon name="icon-V" size={14} color="#f86442" />
<Text style={{ marginLeft: 5 }}>{item.played}</Text>
</View>
<View style={styles.playingView}>
<Icon name="icon-shengyin" size={14} color="#f86442" />
<Text style={{ marginLeft: 5 }}>{item.playing}</Text>
</View>
</View>
</View>
</View>
</TouchableOpacity>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#fff',
margin: 10,
borderRadius: 8,
shadowOffset: { width: 0, height: 5 },
shadowOpacity: 0.5,
shadowRadius: 10,
shadowColor: '#ccc',
elevation: 80,
},
item: {
flexDirection: 'row',
padding: 10,
},
image: {
width: 100,
height: 100,
borderRadius: 8,
marginRight: 10,
backgroundColor: '#dedede',
},
rightView: {
flex: 1,
},
titleText: {
fontSize: 16,
marginBottom: 10,
},
remarkText: {
backgroundColor: '#f8f8f9',
padding: 5,
},
bottomView: {
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'flex-end',
},
playedView: {
flexDirection: 'row',
alignItems: 'center',
},
playingView: {
flexDirection: 'row',
alignItems: 'center',
},
});
export default ChannelItem;
2. 在 Home 组件中使用 FlatList
import React from 'react';
import { View, FlatList, StyleSheet } from 'react-native';
import { connect, ConnectedProps } from 'react-redux';
import { RootState } from '@/models/index';
import ChannelItem from './ChannelItem';
interface IProps extends ConnectedProps<typeof connector> {
onPress: (item: IChannel) => void;
}
class Home extends React.PureComponent<IProps> {
componentDidMount() {
this.loadChannelList();
}
loadChannelList = () => {
const { dispatch } = this.props;
dispatch({
type: 'home/fetchChannelList',
});
};
renderItem = ({ item }: { item: IChannel }) => {
return (
<ChannelItem
item={item}
onPress={(item) => this.props.onPress(item)}
/>
);
};
render() {
const { channelList } = this.props;
return (
<View style={styles.container}>
<FlatList
style={styles.scrollview}
data={channelList}
renderItem={this.renderItem}
keyExtractor={(item) => item.id}
/>
</View>
);
}
}
const mapStateToProps = ({ home }: RootState) => ({
channelList: home.channelList,
});
const connector = connect(mapStateToProps);
export default connector(Home);
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#f5f5f5',
},
scrollview: {
flex: 1,
},
});
三、性能优化
1. 使用 PureComponent
将 ChannelItem 组件继承自 React.PureComponent,以避免不必要的组件重渲染。
2. 使用 React.memo
对于函数组件,可以使用 React.memo 进行优化:
const Touchable = React.memo((props: TouchableOpacityProps) => (
<TouchableOpacity activeOpacity={0.8} {...props} />
));
3. 使用 keyExtractor
在 FlatList 中使用 keyExtractor 函数,为每个列表项生成唯一的 key:
keyExtractor={(item) => item.id}
四、总结
在本节中,我们完成了首页列表的开发,包括数据请求、列表展示、点击事件处理和性能优化。通过合理的组件拆分和性能优化,可以显著提升应用的性能和用户体验。下一节,我们将继续完善首页的功能。