zoukankan      html  css  js  c++  java
  • React Native——组件FlatList

    属性

    添加头部组件

    ListHeaderComponent属性用来给FlatList添加头部组件 
    简单使用:

    //ES6之前写法
    _header = function () {
      return (
        <Text style={{fontWeight: 'bold', fontSize: 20}}>热门电影</Text>
      );
    }
    
    
    <FlatList
    ListHeaderComponent={this._header}//header头部组件
    />

    添加尾部组件

    ListFooterComponent属性为FlatList添加尾部组件,接收的参数跟ListHeaderComponent相同。

    //ES6的写法
    _footer = () => (
      <Text style={{fontSize: 14, alignSelf: 'center'}}>到底啦,没有啦!</Text>
    )
    
    <FlatList
      ListFooterComponent={this._footer} //添加尾部组件
    />

    添加头部和尾部组件比较简单,需要注意的就是上边两者ES5和6写法的区别!

    添加分割线

    ItemSeparatorComponent属性可以为FlatList列表之间添加分割线。 
    举个例子:

    class ItemDivideComponent extends Component {
      render() {
        return (
          <View style={{height: 1, backgroundColor: 'skyblue'}}/>
        );
      }
    };
    
    
    <FlatList
      ItemSeparatorComponent={ItemDivideComponent}//分割线组件
    />

    这里我们自定义了一个组件来设置分割线,当然我们像添加头部和尾部一样,在内部声明之后使用this._header的写法也是可以的!

    设置空数据视图

    ListEmptyComponent属性,可以为FlatList设置一个没有数据的时候展示的视图!,这个属性可以接收的参数类型比较多,可以是React Component,也可以是一个render函数,或者渲染好的element。 
    所以设置空数据视图不仅可以像前边介绍的两种方式以外,还可以接收一个render函数。 
    举个例子:

    createEmptyView() {
      return (
       <Text style={{fontSize: 40, alignSelf: 'center'}}>还没有数据哦!</Text>
      );
    }
    
    <FlatList
      ListEmptyComponent={this.createEmptyView()}
    />

    设置item的key

    在前一篇博客中,我们的设置data的时候,是这样的:

    data={[
      {key: '大护法'},
      {key: '绣春刀II:修罗战场'},
      ...         
    ]}

    类似{key:你的数据value}这样的形式,是因为我们在设置data的时候,必须要为item设置key属性,否则会有一个黄色的警告弹出。而且我们需要注意的是这里每一个item的key是唯一的!,如果按照这样的写法,我们在数据中有重复的,比如{key: '大护法'},{key: '大护法'},这里的大护法只会显示一个,因为FlatList会认为这是一条数据,因为key相同! 
    那么为什么会这样? 
    因为FlatList中有一个属性:keyExtractor,用于为给定的item生成一个不重复的key若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标index。因为前边没有指定该属性,所以就把item.key作为了key值,才会认定两个重复的数据是一条数据!

    那么一般地,我们可以这样使用:

    _keyExtractor = (item, index) => index;
    
    <FlatList
      keyExtractor={this._keyExtractor}
    />

    这样就把data中数组的下标作为了唯一的key。 
    那么在data中指定数据的时候,就不用{key: '大护法'}这样写了,因为我们已经指定了唯一的key,而可以随意写{name: '大护法'}或者{movie: '大护法'},在渲染item的时候,取值用item.name或者item.movie即可!也不会有黄色的警告出现!

    你明白了吗?

    设置itemLayout

    getItemLayout属性是一个可选的优化,用于避免动态测量内容尺寸的开销。如果我们知道item的高度,就可以为FlatList指定这一个属性,来使FlatList更加高效的运行! 
    举个例子:

    getItemLayout={(data, index) => ({
      length: 44, offset: (44 + 1) * index, index
    })}

    我们在上边使用的时候指定了item的高度为44,所以length参数为44;我们设置了分割线,且指定分割线的高度是1,所以offset参数为44+1。综合来看,设置这个属性应这样写:

    getItemLayout={(data, index) => ({
      length: 你的item的height, offset: (你的item的height + ItemSeparator的height) * index, index
    })}

    设置这一属性,在调用FlatList的跳转函数的时候非常有用,否则可能会很卡顿!如scrollToEnd(),scrollToIndex(),这两个方法后边再说!

    下拉刷新

    FlatList中有两个属性,可以用来设置下拉刷新。

    • refreshing在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号.
    • onRefresh如果设置了此选项,则会在列表头部添加一个标准的RefreshControl控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing属性。

    这里的RefreshControl控件,非常类似于Android v4包中的SwipeRefreshLayout,这里就不多说了,需要了解的可以查看相关文档!

    如何使用,举个例子:

    refreshing={this.state.refreshing}
    onRefresh={() => {
      this.setState({refreshing: true})//开始刷新
      //这里模拟请求网络,拿到数据,3s后停止刷新
      setTimeout(() => {
        alert('没有可刷新的内容!');
        this.setState({refreshing: false});//停止刷新
      }, 3000);
    }}

    上拉加载

    关于上拉加载,FlatList也封装有两个属性来实现:

    • onEndReachedThreshold:这个属性决定当距离内容最底部还有多远时触发onEndReached回调。需要注意的是此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。所以它的取值范围为:(0,1),不包含0和1。
    • onEndReached:列表被滚动到距离内容最底部不足onEndReachedThreshold设置的的距离时调用。

    具体使用,举个例子:

    onEndReachedThreshold={0.1}
    onEndReached={({distanceFromEnd}) => (
      setTimeout(() => {
        this.setState((state) => ({
          data: state.data.concat(this._newData),
        }));
      }, 3000)
    )}

    这里我们设置的距离为列表可见长度的1/10,而触发了onEndReached函数时,我们设置了一个定时器,3s后,将data中的数据添加了新数据,从而达到上拉加载更多的效果!

    函数

    介绍

    FlatList下有两个比较常用的函数:

    scrollToEnd() 滚动到底部。如果不设置getItemLayout属性的话,可能会比较卡。
    scrollToIndex()如果不设置getItemLayout属性的话,无法跳转到当前可视区域以外的位置。

    如官方所言,使用这两个函数的时候,最好指定设置getItemLayout属性

    使用

    因为这两个是FlatList组件的函数,所以在使用这两个函数之前,首先我们要得到FlatList组件的引用。 
    这时候就需要ref属性react提供的这个ref属性,表示为对组件真正实例的引用。 
    关于ref属性的使用,可以去React官网查看API!

    具体的使用:

    ref={(flatList) => this._flatList = flatList}
    
    
    this._flatList.scrollToEnd();
    
    //viewPosition参数:0表示顶部,0.5表示中部,1表示底部
    this._flatList.scrollToIndex({viewPosition: 0, index: this.state.text});

    至此,关于FlatList进阶的相关基础内容就说完了!

    完整的Demo

    class FlatListTest extends Component {
      constructor(props) {
        super(props);
        this.state = {
          data: this._sourceData,
          refreshing: false, //初始化不刷新
          text: ''//跳转的行
        };
      }
    
      _header = function () {
        return (
          <Text style={{fontWeight: 'bold', fontSize: 20}}>热门电影</Text>
        );
      }
    
      _footer = () => (
        <Text style={{fontSize: 14, alignSelf: 'center'}}>到底啦,没有啦!</Text>
      )
    
      createEmptyView() {
        return (
          <Text style={{fontSize: 40, alignSelf: 'center'}}>还没有数据哦!</Text>
        );
      }
    
      //此函数用于为给定的item生成一个不重复的key
      //若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标index。
      _keyExtractor = (item, index) => index;
    
      itemClick(item, index) {
        alert('点击了第' + index + '项,电影名称为:' + item.name);
      }
    
      _renderItem = ({item, index}) => {
        return (
          <TouchableOpacity
            activeOpacity={0.5}
            onPress={this.itemClick.bind(this, item, index)}>
            <Text style={flatListStyles.item}>{item.name}</Text>
          </TouchableOpacity>
        );
      }
    
      //点击按钮跳转
      onButtonPress() {
        //viewPosition参数:0表示顶部,0.5表示中部,1表示底部
        this._flatList.scrollToIndex({viewPosition: 0, index: this.state.text});
        //this._flatList.scrollToOffset({ animated: true, offset: 2000 });
      };
    
      onBtnPress2Botton() {
        this._flatList.scrollToEnd();
      }
    
      _sourceData = [
        {name: '大护法'},
        {name: '绣春刀II:修罗战场'},
        {name: '神偷奶爸3'},
        {name: '神奇女侠'},
        {name: '摔跤吧,爸爸'},
        {name: '悟空传'},
        {name: '闪光少女'},
        {name: '攻壳机动队'},
        {name: '速度与激情8'},
        {name: '蝙蝠侠大战超人'},
        {name: '攻壳机动队'},
        {name: '速度与激情8'},
        {name: '蝙蝠侠大战超人'}
      ]
    
      _newData = [{name: '我是新添加的数据1'},
        {name: '我是新添加的数据2'},
        {name: '我是新添加的数据3'}]
    
      render() {
        return (
          <View style={flatListStyles.container}>
            <View style={{flexDirection: 'row', justifyContent: 'center', alignItems: 'center'}}>
              <TextInput
                style={{flex: 1}}
                placeholder="请输入要跳转的行号"
                onChangeText={(text) => this.setState({text})}
              />
              <Button title="跳转到行" onPress={this.onButtonPress.bind(this)} color={'skyblue'}/>
              <Button title="跳转到底部" onPress={this.onBtnPress2Botton.bind(this)} color={'green'}/>
    
            </View>
            <FlatList
              data={this.state.data}
              //使用 ref 可以获取到相应的组件
              ref={(flatList) => this._flatList = flatList}
              ListHeaderComponent={this._header}//header头部组件
              ListFooterComponent={this._footer}//footer尾部组件
              ItemSeparatorComponent={ItemDivideComponent}//分割线组件
              //空数据视图,可以是React Component,也可以是一个render函数,或者渲染好的element。
              ListEmptyComponent={this.createEmptyView()}
              keyExtractor={this._keyExtractor}
              //是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你可以提前知道内容的高度。
              //如果你的行高是固定的,getItemLayout用起来就既高效又简单.
              //注意如果你指定了SeparatorComponent,请把分隔线的尺寸也考虑到offset的计算之中
              getItemLayout={(data, index) => ( {length: 44, offset: (44 + 1) * index, index} )}
              //决定当距离内容最底部还有多远时触发onEndReached回调。
              //注意此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。
              onEndReachedThreshold={0.1}
              //当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用
              onEndReached={({distanceFromEnd}) => (
                setTimeout(() => {
                  this.setState((state) => ({
                    data: state.data.concat(this._newData),
                  }));
                }, 3000)
              )}
              refreshing={this.state.refreshing}
              onRefresh={() => {
                this.setState({refreshing: true})//开始刷新
                //这里模拟请求网络,拿到数据,3s后停止刷新
                setTimeout(() => {
                  alert('没有可刷新的内容!');
                  this.setState({refreshing: false});
                }, 3000);
              }}
              renderItem={this._renderItem}
            />
          </View>
        );
      }
    }
    ;
    
    class ItemDivideComponent
      extends Component {
      render() {
        return (
          <View style={{height: 1, backgroundColor: 'skyblue'}}/>
        );
      }
    }
    ;
    
    const flatListStyles = StyleSheet.create({
      container: {
        flex: 1,
        paddingTop: 22
      },
      item: {
        padding: 10,
        fontSize: 18,
        height: 44,
      },
    })
    
    AppRegistry.registerComponent('AwesomeProject', () => FlatListTest);
  • 相关阅读:
    瀑布流布局——JS+绝对定位
    浏览器事件的思考
    css的hack详解
    主流浏览器的Hack写法
    [HTML&CSS] 未知高度多行文本垂直居中
    HTML标签的默认样式列表
    推荐的 CSS 书写顺序
    高效整洁CSS代码原则 (上)
    高效整洁CSS代码原则 (下)
    Xcode升级导致插件失效的解决办法
  • 原文地址:https://www.cnblogs.com/CrazyWL/p/7347533.html
Copyright © 2011-2022 走看看