React Native 中更优的列表视图
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
自从我们在社区群组的预告发布后,许多开发者已经开始尝试使用新的列表组件。今天我们正式宣布:告别繁琐的 ListView 和 DataSource,不再有陈旧行项、未修复的 bug 或内存占用过高的问题!通过最新的 React Native 2017 年 3 月候选版本 (0.43-rc.1),您可以从全新组件套件中选择最适合需求的方案,开箱即享卓越性能和丰富功能:
<FlatList>
这是实现简单高效列表的主力组件。只需提供数据数组和 renderItem 渲染函数即可立即使用:
<FlatList
data={[{title: 'Title Text', key: 'item1'}, ...]}
renderItem={({item}) => <ListItem title={item.title} />}
/>
<SectionList>
当您需要渲染按逻辑分块的数据(例如带分节标题的字母顺序通讯录),或处理异构数据及渲染模式(比如个人资料页:按钮组 + 发布框 + 照片网格 + 好友网格 + 动态列表)时,这正是理想选择。
<SectionList
renderItem={({item}) => <ListItem title={item.title} />}
renderSectionHeader={({section}) => <H1 title={section.key} />}
sections={[ // homogeneous rendering between sections
{data: [...], key: ...},
{data: [...], key: ...},
{data: [...], key: ...},
]}
/>
<SectionList
sections={[ // heterogeneous rendering between sections
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
{data: [...], key: ..., renderItem: ...},
]}
/>
<VirtualizedList>
底层实现组件,提供更灵活的 API。特别适用于非常规数组结构(如不可变列表)的数据源。
功能亮点
列表组件应用场景广泛,因此我们为全新组件集成了开箱即用的丰富功能:
-
滚动加载 (
onEndReached) -
下拉刷新 (
onRefresh/refreshing) -
可配置的可视区域回调 (
onViewableItemsChanged/viewabilityConfig) -
横向模式 (
horizontal) -
智能行项与分节分隔符
-
多列布局 (
numColumns) -
精准滚动控制 (
scrollToEnd,scrollToIndex,scrollToItem) -
增强的 Flow 类型支持
注意事项
-
当行项子树滚动出渲染窗口时,其内部状态不会被保留。请确保所有数据都存储在行项数据或外部状态库(如 Flux、Redux 或 Relay)中
-
这些组件基于
PureComponent实现,意味着当props保持浅层相等时不会重新渲染。请确保renderItem函数直接依赖的所有数据都通过 props 传递,且更新后引用发生变化(非===相等),否则界面可能不会响应变更。这包括data属性和父组件状态。例如:<FlatList
data={this.state.data}
renderItem={({item}) => (
<MyItem
item={item}
onPress={() =>
this.setState(oldState => ({
selected: {
// New instance breaks `===`
...oldState.selected, // copy old data
[item.key]: !oldState.selected[item.key], // toggle
},
}))
}
selected={
!!this.state.selected[item.key] // renderItem depends on state
}
/>
)}
selected={
// Can be any prop that doesn't collide with existing props
this.state.selected // A change to selected should re-render FlatList
}
/> -
为控制内存占用并确保滚动流畅,列表内容会在屏幕外异步渲染。这意味着用户可能快速滚动时暂时看到空白区域,这是为平衡性能所做的设计取舍。我们正在持续优化该体验。
-
默认情况下,新列表组件会读取每项的
key属性作为 React 键值。您也可通过自定义keyExtractor属性指定键值生成逻辑。
性能表现
新版列表组件在简化 API 的同时实现了显著的性能提升,核心突破在于无论行数多少都能保持近乎恒定的内存占用。这是通过「虚拟化」技术实现的:当元素滚出渲染窗口时,会将其从组件树中完全卸载,释放 React 组件的 JS 内存、影子树及原生视图的内存。请注意:组件内部状态不会被保留,务必通过 Relay/Redux/Flux 等外部状态管理工具保存关键数据。
限制渲染窗口还减少了 React 和原生平台的工作量(例如视图遍历)。即使渲染百万级列表的末尾项,也无需遍历全部元素。您甚至可通过 scrollToIndex 直接跳转至列表中部,而无需额外渲染。
我们改进了渲染调度机制以提升应用响应性:位于渲染窗口边缘的项会在手势/动画等交互完成后,以较低优先级进行非频繁渲染。
高级用法
与 ListView 不同,新版列表在任意属性变更时会重新渲染窗口内的所有项。由于窗口渲染保持了恒定数量,通常不会影响性能。但若列表项结构复杂,建议在子组件中使用 React.PureComponent 或 shouldComponentUpdate 遵循 React 性能优化实践。
若能在不实际渲染的情况下预计算行高,可通过 getItemLayout 属性提升用户体验。这将使 scrollToIndex 等跳转操作更流畅,并优化滚动指示器显示(无需渲染即可确定内容高度)。
若使用不可变列表等特殊数据结构,请选用 <VirtualizedList> 组件。它通过 getItem 属性支持按索引获取数据,并具有更宽松的 Flow 类型约束。
我们还提供多项参数应对特殊场景:通过 windowSize 平衡内存占用与用户体验;用 maxToRenderPerBatch 调节填充速度与响应性;通过 onEndReachedThreshold 控制滚动加载触发时机等。
未来计划
-
迁移现有场景(最终弃用
ListView) -
按需求增补功能(欢迎反馈!)
-
粘性分组头部支持
-
深度性能优化
-
支持带状态的函数式列表项组件