ReactNative 应用 ListView 实现分组列表

举报
SHQ5785 发表于 2023/04/21 09:32:06 2023/04/21
【摘要】 一、前言在前期博文中讲解了应用SectionList实现分组列表,本文主要讲解ReactNative长列表数据展示核心组件ListView ,该组件在数据量大时性能较差,占用内存持续增加,故诞生了FlatList组件。 二、ListView 常用属性ScrollView 相关属性样式全部继承属性名(类型)说明dataSource 【ListViewDataSource】设置ListView...

一、前言

在前期博文中讲解了应用SectionList实现分组列表,本文主要讲解ReactNative长列表数据展示核心组件ListView ,该组件在数据量大时性能较差,占用内存持续增加,故诞生了FlatList组件。

二、ListView 常用属性

ScrollView 相关属性样式全部继承

属性名(类型) 说明
dataSource 【ListViewDataSource】 设置ListView的数据源
initialListSize【number】 设置ListView组件刚刚加载的时候渲染的列表行数,用这个属性确定首屏或者首页加载的数量,而不是花大量的时间渲染加载很多页面数据,提高性能。
onChangeVisibleRows【function (visibleRows,changedRows)=>void 当可见的行发生变化的时候回调该方法。
onEndReachedThreshold 【number] 当偏移量达到设置的临界值调用onEndReached
onEndReached 【function】 当所有的数据项行被渲染之后,并且列表往下进行滚动。一直滚动到距离底部onEndReachedThredshold设置的值进行回调该方法。原生的滚动事件进行传递(通过参数的形式)。
pageSize 【number】 每一次事件的循环渲染的行数
removeClippedSubviews【 bool】 该属性用于提供大数据列表的滚动性能。该使用的时候需要给每一行(row)的布局添加over:'hidden'样式。该属性默认是开启状态。
renderFooter 【function ()=>renderable】 在每次渲染过程中头和尾总会重新进行渲染。如果发现该重新绘制的性能开销比较大的时候,可以使用StaticContainer容器或者其他合适的组件。
renderHeader 【function】 在每一次渲染过程中Footer(尾)该会一直在列表的底部,header(头)该会一直在列表的头部,用法同上。
renderRow 【function (rowData,sectionID,rowID,highlightRow)=>renderable】 该方法有四个参数,其中分别为数据源中一条数据,分组的ID,行的ID,以及标记是否是高亮选中的状态信息。
renderScrollComponent 【function (props)=>renderable】 该方法可以返回一个可以滚动的组件。默认该会返回一个ScrollView
renderSectionHeader 【function (sectionData,sectionID)=>renderable】 如果设置了该方法,这样会为每一个section渲染一个粘性的header视图。该视图粘性的效果是当刚刚被渲染开始的时候,该会处于对应的内容的顶部,然后开始滑动的时候,该会跑到屏幕的顶端。直到滑动到下一个section的header(头)视图,然后被替代为止。
renderSeparator 【function (sectionID,rowID,adjacentRowHighlighted)=>renderable】 如果设置该方法,会在被每一行的下面渲染一个组件作为分隔。除了每一个section分组的头部视图前面的最后一行。
scrollRenderAheadDistance 【number】 进行设置当该行进入屏幕多少像素以内之后就开始渲染该行

三、ListView 高阶特性

ListView同样支持一些高级特性,包括设置每一组的粘性头部(类似于iPhone)、支持设置列表的header以及footer视图、当数据列表滑动到最底部的时候支持onEndReached方法回调、设备屏幕列表可见的视图数据发生变化的时候回调onChangeVisibleRows以及一些性能方面的优化特性。

ListView设计的时候,当需要动态加载非常大的数据的时候,下面有一些方法性能优化的方法可以让ListView滚动的时候更加平滑:

只更新渲染数据变化的那一行 ,rowHasChanged方法会告诉ListView组件是否需要重新渲染当前那一行。

选择渲染的频率,默认情况下每一个event-loop(事件循环)只会渲染一行(可以同pageSize自定义属性设置)。这样可以把大的工作量进行分割,提供整体渲染的性能。

四、ListView Demo

/**
 * Sample React Native App
 * https://github.com/facebook/react-native
 * @flow
 */

import React, {Component} from 'react';
import {
  AppRegistry,
  StyleSheet,
  Text,
  View,
  Image,
  ListView,
  TouchableOpacity,
  AlertIOS,
} from 'react-native';

var Dimensions = require('Dimensions');
var {width, height} = Dimensions.get('window');
// 引入数据文件
var models = require("./Wine.json");

var listViewTest = React.createClass({

  /**
   * 生命周期,不可更改的属性在这里
   * @returns {{}}
   */
  getDefaultProps() {
    return {}
  },
  /**
   * 生命周期,状态机在这里
   * @returns {{}}
   */
  getInitialState() {
    // 创建数据源   rowHasChanged方法决定了ListView是否重新渲染当前这一行
    var ds = new ListView.DataSource({
      rowHasChanged: (r1, r2) => {
        r1 !== r2
      }
    });
    return {
      // 数据源中的数据
      dataSource: ds.cloneWithRows(models)
    }
  },
  /**
   * 生命周期,复杂的操作在这里
   */
  componentDidMount() {

  },
  /**
   * 生命周期,渲染
   * @returns {XML}
   */
  render() {
    return (
      <ListView
        dataSource={this.state.dataSource} // 指定数据源
        renderRow={this.renderRow} // 渲染每一行
      />
    );
  },
  /**
   * ListView根据数据源的数据进行渲染
   * @param rowData 每一项的数据
   * @param sectionID 组号
   * @param rowID 行号
   * @param highlightRow
   * @returns {XML}
   */
  renderRow(rowData, sectionID, rowID, highlightRow) {
    return (
      <TouchableOpacity 
        activeOpacity={0.7} 
        onPress={() => this.cellDidClick(rowID, rowData)}
      >
        <View style={styles.wineCell}>
          <Image style={styles.icon} source={{uri: rowData.image}}/>
          <View style={styles.titleContainer}>
            <Text style={styles.title}>{rowData.name}</Text>
            <Text style={styles.subTitle}>${rowData.money}</Text>
          </View>
        </View>
      </TouchableOpacity>
    );
  },

  cellDidClick(rowID, rowData) {
    alert("点击了" + rowID + rowData.name);
  }
});

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
    paddingTop: 20
  },
  wineCell: {
    flexDirection: "row",
    borderBottomWidth: 1,
    borderBottomColor: '#eee',
    paddingLeft: 10,
    paddingTop: 10,
    paddingBottom: 10,
    backgroundColor: 'white'
  },
  icon: {
    width: 60,
    height: 60,
  },
  titleContainer: {
    flexDirection: "column",
    justifyContent: 'space-between'
  },
  title: {
    fontSize: 15,
    fontWeight: 'bold',
    width: width - 60,
    paddingLeft: 10,
    paddingRight: 10
  },
  subTitle: {
    fontSize: 15,
    marginLeft: 10,
  }
});

AppRegistry.registerComponent('listViewTest', () => listViewTest); 

五、拓展阅读

【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。