React Native控件之ListView

来源:互联网 发布:java前端和后端的区别 编辑:程序博客网 时间:2024/04/30 18:07

概述

ListView作为核心组件之一,主要用于高效地显示一个可以垂直滚动的变化的数据列表。经过自定义组装,我们还可以用它实现九宫格等页面效果。
在React Native中,使用ListView组件至少需要两个属性:DataSource和renderRow。DataSource是需要渲染界面的数据源,renderRow是根据数据源的元素返回的可渲染的组件,即ListView的一行。
在React Native中,最基本的使用方式就是创建一个ListView.DataSource数据源,然后给它传递一个普通的数据数组,再使用数据源来实例化一个ListView组件,并且定义它的renderRow回调函数,这个函数返回ListView的一行作为一个可渲染的组件。例如,官网提供的ListView示例:

constructor(props) {  super(props);  var ds = new ListView.DataSource({rowHasChanged: (r1, r2) => r1 !== r2});  this.state = {    dataSource: ds.cloneWithRows(['第一行', '第二行', '第三行']),  };}//省略…render() {  return (    <ListView      dataSource={this.state.dataSource}      renderRow={(rowData) => <Text>{rowData}</Text>}    />  );}

属性

ListView组件主要有两个属性:dataSource和renderRow。其他常用的属性如下:
dataSource 数据源
renderRow ListView渲染的每一item view
initialListSize 初始渲染item的个数
pageSize 每次事件循环(每帧)渲染的行数
onEndReachedThreshold 调用onEndReached之前的临界值,单位是像素
onEndReached 当所有的数据都已经渲染过,并且列表被滚动到距离最底部不onEndReachedThreshold个像素的距离时调用

获取网络数据渲染界面

从现在开始,我们将实现一个从网络获取数据并使用ListView控件渲染界面的过程。效果如下:
这里写图片描述

1,创建构造器

我们在构造器中声明了一个成员变量state,并为它定义了两个属性,dataSource和loaded 。

constructor(props) {      super(props);      this.state = {          dataSource: new ListView.DataSource({              rowHasChanged: function(row1, row2) {return row1 !== row2},          }),          loaded: false,      };  }

由于dataSource是弱类型,所以不用声名类型,重点看ListView实例化的部分。rowHasChanged是ListView必须要实现的一个function,否则会报错。一般我们会使用下面的简洁写法:

rowHasChanged: (row1, row2) => row1 !== row2  

2,处理componentDidMount回调

Component有一个回调函数componentDidMount(),它在所有UI组建加载完成后会被调用,类似于Android中Activity生命周期的onCreate,通常我们在它被回调的时候发起网络请求。

componentDidMount(){  this.fetchData();  }  

fetchData方法是我们自定义的请求网络的方法 。

 fetchData() {       fetch(REQUEST_URL)           .then((response) => response.json())           .then((responseData) => {   console.log(responseData);               this.setState({                   dataSource: this.state.dataSource.cloneWithRows(responseData.movies),                   loaded: true,               });           }).catch(function(e){         })           .done();   }  

当网络返回数据之后,我们需要对dataSource进行通知更新操作。

3,渲染单个Cell视图

ListView界面由一个一个子视图组成,我们需要在render的时候渲染子视图,通常为了代码维护的方便,我们会将子视图通过自定义为视图使用。

renderCell(cellData) {       return (           <View style={styles.cellContainer}>               <Image                  //  source={{uri:cellData.pic}}                  source={require('./image/defalt_image.png')}                   style={styles.thumbnail}               />               <View style={styles.itemCellView}>                   <Text numberOfLines={1} style={styles.title}>{cellData.title}</Text>                   <Text numberOfLines={1} style={styles.id}>{cellData.actor}</Text>               </View>           </View>       );   }}

4,ListView渲染整个界面

使用ListView渲染整个界面。

return (              <ListView                  dataSource={this.state.dataSource}                  renderRow={this.renderMovie}                  style={styles.listView}              />          );

以下为全部代码:

import React, {      Component,  } from 'react';  import {       AppRegistry,       Image,       StyleSheet,       Text,       View,       ListView,   } from 'react-native';   var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';   class DemoProject extends Component   {       constructor(props) {           super(props);           this.state = {               dataSource: new ListView.DataSource({                   rowHasChanged: (row1, row2) => row1 !== row2,               }),               loaded: false,           };       }       componentDidMount(){           this.fetchData();       }       fetchData() {           fetch(REQUEST_URL)               .then((response) => response.json())               .then((responseData) => {                   console.log(responseData);                   this.setState({                       dataSource: this.state.dataSource.cloneWithRows(responseData.movies),                       loaded: true,                   });               }).catch(function(e){               })               .done();       }       render() {           if (!this.state.loaded) {               return this.renderLoadingView();           }           return (               <ListView                   dataSource={this.state.dataSource}                   renderRow={this.renderMovie}                   style={styles.listView}               />           );       }       renderLoadingView()       {           return (<View style={styles.container} >                   <Text>Loading movies......</Text>               </View>           );       }       renderMovie(movie) {           return (               <View style={styles.container}>                   <Image                       source={{uri: movie.posters.thumbnail}}                       style={styles.thumbnail}                   />                   <View style={styles.rightContainer}>                       <Text style={styles.title}>{movie.title}</Text>                       <Text style={styles.year}>{movie.year}</Text>                   </View>               </View>           );       }   };   var styles = StyleSheet.create({       container: {           flex: 1,           flexDirection: 'row',           justifyContent: 'center',           alignItems: 'center',           backgroundColor: '#F5FCFF',       },       rightContainer: {           flex: 1,       },       title: {           fontSize: 20,           marginBottom: 8,           textAlign: 'center',       },       year: {           textAlign: 'center',       },       thumbnail: {           width: 53,           height: 81,       },       listView: {           paddingTop: 20,           backgroundColor: '#F5FCFF',       },   });   AppRegistry.registerComponent('AwesomeProject', () => DemoProject);  

注:如果你读取的是本地的数据,可以通过require获取,例如:

let data=require('./data/list.json');      this.setState({          dataSource:this.state.dataSource.cloneWithRows(data.list),      });

附:ListView示例代码

0 0