9-6 猜你喜欢

109 阅读2分钟

在本节中,我们将编写“猜你喜欢”组件,该组件用于展示一个九宫格的卡片布局。

一、创建 Model

models/home.ts 中添加以下内容:

  1. 声明接口地址

    const GUESS_URL = '/mock/11/bear/guess';
    
  2. 定义 Guess 接口

    interface IGuess {
      id: string;
      title: string;
      image: string;
    }
    
  3. HomeState 中定义 guess 属性

    export interface HomeState {
      carousels: ICarousel[];
      guess: IGuess[];
    }
    
  4. effects 中定义请求猜你喜欢的列表数据

    effects: {
      *fetchGuess(_, { call, put }) {
        const { data } = yield call(axios.get, GUESS_URL);
        yield put({
          type: 'setState',
          payload: {
            guess: data,
          },
        });
      },
    },
    

二、创建组件

pages/Home/Guess.tsx 中创建组件:

import React from 'react';
import { View, Text, Image, FlatList, StyleSheet, TouchableOpacity } from 'react-native';
import { connect, ConnectedProps } from 'react-redux';
import { RootState } from '@/models/index';

interface IProps extends ConnectedProps<typeof connector> {}

class Guess extends React.PureComponent<IProps> {
  componentDidMount() {
    this.fetchGuessData();
  }

  fetchGuessData = () => {
    const { dispatch } = this.props;
    dispatch({
      type: 'home/fetchGuess',
    });
  };

  renderItem = ({ item }: { item: IGuess }) => {
    return (
      <TouchableOpacity style={styles.item} onPress={() => alert('点击')}>
        <Image source={{ uri: item.image }} style={styles.image} />
        <View style={styles.rightContainer}>
          <Text numberOfLines={2}>{item.title}</Text>
        </View>
      </TouchableOpacity>
    );
  };

  render() {
    const { guess } = this.props;
    return (
      <View style={styles.container}>
        <View style={styles.header}>
          <View style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Icon name="icon-xihuan" />
            <Text style={styles.headerTitle}>猜你喜欢</Text>
          </View>
          <View style={{ flexDirection: 'row', alignItems: 'center' }}>
            <Text style={styles.moreTitle}>更多</Text>
            <Icon name="icon-more" />
          </View>
        </View>
        <FlatList
          numColumns={3}
          data={guess}
          renderItem={this.renderItem}
          keyExtractor={(item) => item.id}
          style={styles.list}
        />
        <TouchableOpacity style={styles.changeGuess} onPress={this.fetchGuessData}>
          <Text>
            <Icon name="icon-huanyipi" size={14} color="red" /> 换一批
          </Text>
        </TouchableOpacity>
      </View>
    );
  }
}

const mapStateToProps = ({ home }: RootState) => ({
  guess: home.guess,
});

const connector = connect(mapStateToProps);

export default connector(Guess);

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#ffffff',
    borderRadius: 8,
    margin: 16,
    shadowOffset: { width: 0, height: 5 },
    shadowOpacity: 0.5,
    shadowRadius: 10,
    shadowColor: '#ccc',
    elevation: 4,
  },
  header: {
    padding: 15,
    flexDirection: 'row',
    justifyContent: 'space-between',
    borderBottomColor: '#efefef',
    borderBottomWidth: StyleSheet.hairlineWidth,
  },
  headerTitle: {
    marginLeft: 5,
    color: '#333333',
  },
  moreTitle: {
    color: '#6f6f6f',
  },
  list: {
    paddingTop: 10,
    paddingHorizontal: 10,
  },
  item: {
    flex: 1,
    marginVertical: 6,
    marginHorizontal: 5,
  },
  image: {
    width: '100%',
    height: 100,
    borderRadius: 8,
    marginBottom: 10,
  },
  rightContainer: {
    flex: 1,
  },
  changeGuess: {
    padding: 10,
    alignItems: 'center',
  },
});

三、功能说明

  1. 数据请求

    • 在组件加载时,调用 fetchGuessData 方法,通过 Dva 的 dispatch 请求数据。
    • 数据请求成功后,通过 put 将数据更新到 HomeState 中。
  2. 列表展示

    • 使用 FlatList 组件展示数据,设置 numColumns={3} 实现九宫格布局。
    • 每个列表项使用 TouchableOpacity 实现点击效果。
  3. 换一批功能

    • 点击“换一批”按钮,重新请求数据并更新列表。

四、样式说明

  • 容器样式

    • container:设置背景颜色、圆角、阴影等样式。
    • header:设置头部的布局和样式。
  • 列表项样式

    • item:设置每个列表项的布局和间距。
    • image:设置图片的宽度、高度和圆角。
  • 按钮样式

    • changeGuess:设置按钮的样式和点击效果。

五、总结

在本节中,我们完成了“猜你喜欢”组件的开发,包括数据请求、列表展示、点击事件处理和换一批功能。下一节,我们将在首页添加一个列表页面。