ReactNative基础(四)了解ListView的使用、实现GridView效果、编写一个真实网络请求案例

此博客基于react-native-0.48.4

ListView简介

一个核心组件,用于高效地显示一个可以垂直滚动的变化的数据列表。最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数会接受数组中的每个数据作为参数,返回一个可渲染的组件(作为listview的每一行)

  • ListView文档同时它还有个离不开的ListView.DataSource就好比在Android中的Adapter
  • 虽然现在这个组件已经过期,官方建议使用FlatListSectionList代替
  • 当是我们还是得来学习一下,毕竟以后搞项目遇到了不会一脸懵逼。
现在来实现一个最简单的列表

效果图:

这里写图片描述

  • 首先创建一个MyListView.js组件并创建好数据源
constructor(props) {
    super(props);
    //1.初始化ListView.DataSource数据源
    var data = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});
    this.state = {
        //传入我们需要展示的数据
        data: data.cloneWithRows(this.getArrays()),
    }

}
  • 创建我们的测试数据
//动态获取item内容
getArrays() {
    var list = [];
    for (var i = 0; i < 20; i++) {
        list.push(
            new this.ItemData('我是标题' + '---' + i, '我是内容' + '---' + i, i)
        );
    }
    return list;
}
  • ItemData这个拿Java来说就是一实体类Bean对象
//存储每个item对象的数据
ItemData(title, content, position) {
    this.position = position;
    this.title = title;
    this.content = content;
}

经过上面三步,我们的ListView.DataSource数据源就创建好了,接下来就是对数据进行展示了。

数据的展示 Item布局渲染
render() {
    return (
        <ListView
            //设置数据源
            dataSource={this.state.data}
            //相当于Android中Adapter的getView 渲染每一个Item
            renderRow={this.getView}/>
    )
}
  • 重点就在这个renderRow函数了,渲染每一个Item进行数据展示
/**
 * renderRow中可以使用的参数(rowData, sectionID, rowID, highlightRow)
 * @param rowData
 * @returns {XML}
 */

getView(rowData) {
    //这里返回的就是每个Item
    return (
        <TouchableOpacity activeOpacity={0.5}
                          onPress={() => ToastAndroid.show(rowData.position + '', ToastAndroid.SHORT)}>
            <View style={styles.item}>
                <Text>{rowData.title}</Text>
                <Text style={{marginTop: 5, fontSize: 12}}>{rowData.content}</Text>
            </View>
        </TouchableOpacity>
    )
}

//样式
item: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: 'white',
    borderBottomWidth: 0.5,
    borderBottomColor: '#dddddd',
    height: 60,
}
  • renderRow中可以使用的参数(rowData, sectionID, rowID, highlightRow),具体的使用可以参照官方文档
  • rowData也就是我们一开始初始化好的数据ItemData实例
  • 在Item的最外层套了一层TouchableOpacity用来实现Item的点击事件
  • 使用ListView也就三步:定义ListView.DataSource构造数据源、编写ListViwe、实现renderRow编写Item样式。
当然通过ListView可以实现一个GridView效果,只需要修改一下ListView的主轴方向即可;创建数据源之类操作和上面一样
render() {
    return (
        <ListView
            dataSource={this.state.data}
            contentContainerStyle={styles.list}
            //相当于Android中Adapter的getView 渲染每一个Item
            renderRow={this.getView}
            pageSize={20}/>
    )
}

//样式
list: {
    //横向
    flexDirection: 'row',
    flexWrap: 'wrap',
}
  • pageSize当为横向的时候需要指定这个属性,值就为你要显示数据的大小(暂时不知道为什么要这样,先记录下)
  • 当列表为水平方向且包裹内容时,要达到GridView效果我们需要自己计算每个Item的宽度并且平分屏幕的宽度就可以了。

获取屏幕的宽度,并计算出每一个Item的宽度

//屏幕信息
var dimensions = require('Dimensions');
//获取屏幕的宽度
var {width} = dimensions.get('window');
var columns = 3;//每一行显示多少列
var itemWidth = width / columns;//每一个item所占的宽度

有了宽度我们就需要修改每个Item的宽度和其他样式了,如下:

item: {
    justifyContent: 'center',
    alignItems: 'center',
    borderWidth: 0.5,
    borderColor: '#dddddd',
    width: itemWidth,
    height: 60,
},

效果图:

GridView源码看这里

讲到这里ListView控件的基本使用相信大家已经掌握了,那我们就来写个真实的案例,从服务器请求json数据并通过ListView列表展示。

万物基于效果图:

这里就涉及我们的网络请求和json数据处理来,不过也是很简单的。先来说说第一部分请求网络数据:
  • 可以先看下源码源码在这里,在看这里。
  • 使用fetch()请求接口,我们可以先看下官方的文档网络
  • 我们先来定义我们要请求的接口地址
static defaultProps = {
    url: 'https://news-at.zhihu.com/api/4/news/latest'
};
  • 同时初始化好我们的数据源,此时并没有数据所以知识先创建来一个对象;待会请求到了数据直接往里面放就可以了。
constructor(props) {
    super(props);
    //1.初始化ListView.DataSource数据源
    this.state = {
        data: new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2}),
    }
}
  • 请求数据就只需要在组件渲染完成即可
//渲染完成,请求网络数据
componentDidMount() {
    fetch(this.props.url)
        //将响应到的数据转化为json
        .then((response) => response.json())
        .then((response) => {
            //解析json数据
            var json = response['stories'];
            //更新状态机
            this.setState({
                data: this.state.data.cloneWithRows(json),
            });
        })
        .catch((error) => {
            if (error) {
                //网络错误处理
                console.log('error', error);
            }
        })
}

来看下返回的数据格式,这样结合代码会更加的直观

{
  "date": "20170928",
  "stories": [
    {
      "images": [
        "https://pic2.zhimg.com/v2-6707daba106f3c4286ea497d6e9b9759.jpg"
      ],
      "type": 0,
      "id": 9636088,
      "ga_prefix": "092821",
      "title": "这可能是丁丁出现次数最多的美剧"
    },
    {
      "images": [
        "https://pic1.zhimg.com/v2-629d7c83a17d14f9117f9b3d019e3774.jpg"
      ],
      "type": 0,
      "id": 9635776,
      "ga_prefix": "092819",
      "title": "吸尘器制造商戴森要在 2020 年推出电动汽车,这是 70 岁发明家的野心"
    },
    //...
}

var json = response['stories'];这样就拿到了stories里面的所有数据并且是个数组,数组的每个元素里面有有images数组、typeidga_prefixtitle 也就是下面我们用到的RowData

有了数据源就需要在渲染Item的时候设置在文本上了,展示出来:
getView(rowData) {
    //这里返回的就是每个Item
    return (
        <TouchableOpacity activeOpacity={0.5}
                          onPress={() => ToastAndroid.show(rowData.title, ToastAndroid.SHORT)}>
            <View style={styles.item}>
                {/*左边的图片*/}
                <Image source={{uri: rowData.images[0]}} style={styles.image}/>
                <View style={styles.left}>
                    {/*右边的View*/}
                    <Text style={{marginTop: 15, color: '#333333'}}>{rowData.title}</Text>
                    <View style={styles.content}>
                        <Text style={{flex: 1, textAlign: 'right'}}>{rowData.id + ''}</Text>
                    </View>
                </View>
            </View>
        </TouchableOpacity>
    )
}

个人觉得js上解析json真的是神奇,一个var 遍历定义所有类型很是舒服;哈哈哈…

上面所写的源码点这里UseListView
推荐阅读:
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Code-Porter

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值