React-native之ListView高级属性(16)

一. 简介

ListView加载多数据时经常会用到分页,Gride排列,滚动等高级操作,下面就简单介绍下

分页

当数据量很大的时候如何分页加载 。这种情形分两种情况考虑:
1.数据一次性拿到,边滚动边加载
2.数据不是一次性拿到,而是有可能分屏取数据

对于第一种情况,在 ListView 内部其实已经做了分页的处理:
ListView 内部通过 curRenderedRowsCount 状态保存已渲染的行数;
初始状态下,要加载的数据条数等于 initialListSize (默认为 10 条);
在滚动时检测当前滚动的位置和最底部的距离,如果小于 scrollRenderAheadDistance (默认为 1000),就更新 curRenderedRowsCount ,在它原有值基础上加 pageSize 个(默认为 1 条);
由于属性变化,触发了 ListView 重新的 render 。在渲染过程中, curRenderedRowsCount 起到截断数据的作用,React 的 diff 算法使得只有新加入的数据才会渲染到了界面上。
整个过程类似于 Web 端懒加载机制,即 每次在和底部的距离达到一个阈值时,加载接下来的 pageSize 个数据 。

对于第二种情况,ListView 提供了相关的属性:
onEndReachedThreshold ,在滚动即将到达底部时触发;
onEndReached ,在已经到达底部时触发;
我们可以在这两个方法中调用接口去拿数据,取到数据后再更新数据源。

多列(Grid效果)

很多页面中的列表并非单列的,乍一看似乎要做出不少调整,但实际上只通过布局即可达到相关效果。ListView 并没有强制要求一个 rowData 在展示时一定要占满一行,在多列的情况下,我们适时调整每个 rowData 占据的宽度即可。

React-native之ListView高级属性(16)_第1张图片
gride.png

由于 React Native 使用 Flexbox 进行布局,给ListView设置属性contentContainerStyle;在实现多列时,主要用到的是 flexWrap:wrap 属性:它的效果类似于 float,即水平地排列每一项,当放不下时进行折行处理。在设置每行视图占据一半宽度后就达到了两列的效果,多列的类似。

滚动

ListView 只是整合了数据和展现,但实际滚动的功能还是由 ScrollView 全权负责。ScrollView 实现完全和平台相关:在 iOS 上,它映射为 RCTScrollView ;在 Android 上,它映射为 RCTScrollView 和 AndroidHorizontalScrollView 。
React Native 让不同端上的技术融合在了一起,同时也给开发人员提出了更高的要求。以 ScrollView 为例,大量的属性其实原封不动映射给了 UIScrollView ,这就意味着如果想再深入地研究下去,必须对客户端相关技术有足够了解。无论是前端还是客户端,跳出自己熟悉的那片领域也许才是更进一步的关键。
谈到滚动,有一点不得不说的就是 列表的无限加载 ,这牵涉到滚动的性能。
Github 上的这个 issue 对此展开了热烈的讨论。其中有人就提到,数据量很大情况下,ListView 在加载时所占用的 CPU 和内存会大大增加,滚动到最后就导致了应用 crash。
为此,ListView 中新添加了一个实验性的属性: removeClippedSubviews ,它能在滚动时及时删掉列表中处于视窗的之外的行,以此达到降低内存消耗的目的。不幸的是,即使设置了这个属性,程序虽然各项占用减少了不少,但还是没避免崩溃的命运。处于好奇,在最新版的 ListView 基础上做了简单尝试,不断加载一个无限大的列表,但并没有出现崩溃的情况:
即使加载了 3000、4000 行,Android 真机、iOS 真机和 iOS 模拟器上都没有崩溃;
Android 上明显感到数据加载有 阶段性的延时 ,即滚动一定程度后,再次滚动数据始终加载不出来或要等一段时间才加载出来,体验较差;iOS 相比要流畅的多;
但不崩溃并非最终的目的,很多 React Native 使用者都在试图改进 ListView 的性能表现,相比于直接使用 Native 端的组件,ListView 性能还是差强人意,有很大优化空间。
ListView 并没有创造出新的东西,它只是集各家所长,很好地将 React 的视图渲染和 Native 端很成熟的滚动机制融合在了一起,使用起来和其他组件无差,静态地定义View、动态地组织数据,是给人带来的直观感受。

gride示例

class GrideDemo extends Component { constructor(props){ super(props); this.state={ dataSource:new ListView.DataSource({ rowHasChanged:(row1,row2)=> row1!== row2, }), }; } componentWillMount() { this.fetchData(); } render() { if (!this.state.loaded) { //如果movies==null的情况 初始情况 渲染加载视图 return this.renderLoadingView(); } return ( ); } renderLoadingView() { return ( 正在网络上获取电影数据…… ); } //这是渲染一个电影信息 renderMovie(movie) { return ( {movie.year} ); } fetchData() { fetch(REQUEST_URL) .then((response) => response.json()) .then((responseData) => { this.setState({ dataSource: this.state.dataSource.cloneWithRows(responseData.movies), loaded:true, }); }) .done(); //调用了done() —— 这样可以抛出异常而不是简单忽略 } const styles = StyleSheet.create({ list:{ paddingTop: 20, backgroundColor: '#F5FCFF', }, container: { width:100, height:100, margin:10, justifyContent: 'center', alignItems: 'center', backgroundColor: '#F5FCFF', }, thumbnail: { width: 81, height: 81, borderRadius:10, }, year: { textAlign: 'center', }, gride:{ flexWrap:'wrap', justifyContent:'flex-start', flexDirection:'row' } });

效果

React-native之ListView高级属性(16)_第2张图片
gride_02.png

记录自己的RN学习历程,只用于学习交流。

你可能感兴趣的:(React-native之ListView高级属性(16))