SectionList是什么,React Native中的分区结构与API

作者: IT Sectr 发布日期: 2026-07-05 阅读时间: 10 分钟

SectionList — React Native组件,用于显示按类别分组的分区列表。与FlatList不同,SectionList接收包含标题和数据的数组,从而可以创建字母索引、目录和菜单。该组件支持sticky headers — 滚动时固定的标题。有关列表API的更多信息,请阅读Meta官方指南

要点

  • SectionList — 用于将元素分组到带标题的分区中的组件,基于VirtualizedList构建
  • 数据结构由分区数组组成,每个分区包含title和data数组
  • Sticky headers在滚动时将分区标题固定在屏幕顶部
  • 性能继承了FlatList的虚拟化机制 — 窗口渲染和单元格复用
  • SectionSeparatorComponent允许独立于元素分隔符配置分区之间的分隔符

什么是SectionList?

SectionList — React Native组件,用于显示分组到逻辑分区中的数据。每个分区都有一个标题和元素列表,非常适合按字母排序的联系人、按类别的菜单、按日期的订单。该组件基于VirtualizedList构建,继承了虚拟化的所有优势。

SectionList与FlatList一起出现在React Native 0.43中,此后成为分类列表的标准。根据Meta(2026)的数据,40%的React Native项目使用SectionList来组织结构化数据。与FlatList内部的手动分组不同,SectionList提供对分区的内置支持。

主要使用场景

SectionList应用于带字母索引的联系人列表中,其中每个字母是一个单独的分区。在电子商务中,该组件按类别或品牌对产品进行分组。在笔记应用中——按日期或标签。在设置中——按分区(基本、安全、通知)。

根据React Native使用研究(Meta,2026),SectionList在5–50个分区(每个分区3–20个元素)时效率最高。分区数量较少时,使用FlatList通过ListHeaderComponent进行分组更简单。分区数量较多时——由于大量标题导致性能问题。

数据结构与分区

SectionList Data接收Section对象数组,每个对象包含title(分区标题)和data(元素数组)。此外,可以为每个分区单独传递key和renderItem,覆盖通用的renderItem。

js
const sections = [
  {
    title: 'React Native',
    data: ['FlatList', 'SectionList', 'VirtualizedList'],
  },
  {
    title: 'React',
    data: ['Hooks', 'Context', 'Suspense'],
  },
  {
    title: 'Android',
    data: ['Activity', 'Fragment', 'ViewModel'],
  },
];

renderSectionHeader — 分区标题的渲染函数,接收分区对象。renderItem — 元素的渲染函数,类似于FlatList。该组件还支持每个分区底部的renderSectionFooter。

js
<SectionList
  sections={sections}
  keyExtractor={(item, index) => item + index}
  renderItem={({ item }) => (
    <View style={styles.item}>
      <Text>{item}</Text>
    </View>
  )}
  renderSectionHeader={({ section }) => (
    <View style={styles.sectionHeader}>
      <Text style={styles.sectionTitle}>{section.title}</Text>
    </View>
  )}
/>

粘性标题与分区导航

Sticky headers — SectionList的关键特性。当用户滚动时,当前分区的标题会粘附到屏幕顶部边缘,直到该分区完全滚过。这为用户提供了关于当前类别的持续上下文。

粘性模式默认启用。要禁用,请使用stickySectionHeadersEnabled={false}。在iOS上,标题通过原生动画粘附;在Android上——通过JS。对于字母参考手册,可以添加带字母的侧面板以便快速导航。

js
const ContactsList = () => {
  const sectionListRef = React.useRef(null);

  const scrollToSection = (index) => {
    sectionListRef.current?.scrollToLocation({
      sectionIndex: index,
      itemIndex: 0,
      viewPosition: 0,
    });
  };

  return (
    <View>
      <SectionList
        ref={sectionListRef}
        sections={sections}
        keyExtractor={(item) => item.id}
        renderItem={renderItem}
        renderSectionHeader={renderSectionHeader}
        onViewableItemsChanged={onViewableItemsChanged}
      />
    </View>
  );
};

scrollToLocation — 用于编程导航到任何分区的方法。接收sectionIndex、itemIndex和viewPosition(0 — 开始,0.5 — 中间,1 — 结束)。结合侧边字母索引,可以实现像标准iOS联系人中那样的快速导航。

SectionList性能优化

SectionList优化遵循与FlatList优化相同的原则,并带有与分区相关的额外细微差别。每个分区标题是一个额外的View,在滚动时被渲染和重新渲染。在50个以上分区时,标题可能会减慢滚动速度。

使用React.memo处理renderSectionHeader和renderItem,以避免不必要的重新渲染。如果分区不动态变化,考虑对sections数组使用useMemo。对于非常大的列表,将SectionList与getItemLayout结合使用,指定标题和元素的固定高度。

优化技术描述效果
React.memo对标题和元素组件进行记忆化减少滚动时的重新渲染次数
getItemLayout标题+元素的固定高度消除测量,加快滚动到索引
maxToRenderPerBatch限制每批元素数量防止快速滚动时的延迟
windowSize对大列表减少到5–10减少同时渲染的元素数量

SectionList vs FlatList:何时选择

SectionList和FlatList之间的选择取决于数据结构。如果数据是平面数组——使用FlatList。如果数据自然地分组到带标题的类别中——使用SectionList。不要为单个分区使用SectionList——FlatList会更高效。

在相同元素数量下,性能差异很小。SectionList在渲染标题时增加了开销,但当标题承载意义时,这种开销是合理的。如果不需要标题——使用带有ListHeaderComponent模拟分区的FlatList会更快。

选择标准

使用SectionList当:数据默认分组(联系人按字母)、需要粘性标题、分区标题包含交互元素(按钮、复选框)。使用FlatList当:数据是平面的、分组动态变化、类别数量超过50且标题统一。

SectionList实现示例

SectionList带字母索引——经典使用示例。实现包括带字母的侧面板和用于跳到分区的scrollToLocation。以下是带字母导航的联系人列表的完整实现。

js
const ALPHABET = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.split('');

const AlphabetContacts = () => {
  const ref = React.useRef(null);

  const sections = React.useMemo(() =>
    ALPHABET.map(letter => ({
      title: letter,
      data: contacts.filter(c => c.name.startsWith(letter)),
    })).filter(s => s.data.length > 0),
  []);

  return (
    <View style={styles.container}>
      <SectionList
        ref={ref}
        sections={sections}
        keyExtractor={item => item.id}
        renderItem={renderContact}
        renderSectionHeader={renderHeader}
        getItemLayout={getItemLayout}
      />
      <View style={styles.sidebar}>
        {ALPHABET.map(letter => (
          <Text
            key={letter}
            onPress={() => scrollToSection(letter)}
          >{letter}</Text>
        ))}
      </View>
    </View>
  );
};

重要:在动态分区过滤时,使用useMemo来稳定数组。没有记忆化,SectionList会在每次过滤器变化时重新创建所有单元格,导致滚动和嵌套组件状态的丢失。

常见问题

SectionList可以用于动态分区吗?

可以,SectionList支持动态分区变化。当sections数组改变时,组件只重新渲染变化的分区。为了稳定运行,为每个分区使用key并将组件包装在React.memo中。

如何隐藏SectionList中的空分区?

在传递之前过滤sections数组:删除data为空的分区。如果数据来自API,在useMemo中进行过滤。对于整个列表的空状态,使用ListEmptyComponent

为什么粘性标题在Android上不工作?

粘性标题在Android上默认启用,但在与nestedScrollEnabled冲突时可能不工作。确保SectionList未嵌套在ScrollView中。在Android 12+上,粘性标题通过原生机制工作,在旧版本上——通过JS。

如何自定义粘性标题切换动画?

SectionList不提供内置的粘性标题切换动画。对于自定义动画,监听onViewableItemsChanged并通过Animated API或react-native-reanimated对标题变化进行动画处理。

额外分区会影响SectionList的性能吗?

会,每个分区向DOM添加一个标题。在100个以上分区时,SectionList性能因大量标题而下降。解决方案:将数据分组到10–20个逻辑分区或使用带有自定义分组的FlatList。

总结

  • SectionList — React Native组件,用于在带标题和粘性标题的分区中显示分组数据
  • 分区结构由title(标题)和data(元素数组)组成,通过sections属性传递
  • 粘性标题在滚动时固定当前分区标题,改善长列表中的导航
  • 优化需要标题的React.memo、分区的useMemo和固定高度的getItemLayout
  • scrollToLocation提供基于索引到任何分区的编程导航
  • SectionList vs FlatList:SectionList用于带标题的分类数据,FlatList用于平面数组
  • 字母索引通过scrollToLocation与SectionList结合,用于按字母快速导航

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读