You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Native FlatList中实现图片懒加载?

React Native FlatList 实现视口内图片懒加载方案

当然有办法啦!在React Native里给FlatList实现图片懒加载(只加载进入视口的图片)是非常常见的优化需求,我给你分享两种实用的实现方案:

方案一:利用FlatList原生API手动实现

FlatList本身就提供了监听可见元素的能力,我们可以借助onViewableItemsChanged回调来追踪哪些列表项进入了视口,然后只给这些项加载图片。

实现步骤:

  • 给每个帖子项分配唯一标识(比如item.id)
  • 维护一个状态集合,存储当前可见的帖子ID
  • 通过onViewableItemsChanged更新可见ID集合
  • 列表项组件中,仅当当前帖子ID在可见集合内时,才渲染真实图片,否则显示占位容器/骨架屏

代码示例:

import { useState, useRef } from 'react';
import { FlatList, View, Text, Image } from 'react-native';

const PostList = ({ posts }) => {
  // 存储当前可见的帖子ID集合
  const [visibleItemIds, setVisibleItemIds] = useState(new Set());
  // 配置视口检测规则:当item有50%进入视口时标记为可见
  const viewabilityConfig = useRef({
    itemVisiblePercentThreshold: 50,
  });

  // 监听可见元素变化,更新可见ID集合
  const handleViewableItemsChanged = ({ viewableItems }) => {
    const newVisibleIds = new Set(
      viewableItems.map(item => item.item.id)
    );
    setVisibleItemIds(newVisibleIds);
  };

  const renderPostItem = ({ item }) => {
    return (
      <View style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee' }}>
        <Text style={{ fontSize: 18, marginBottom: 8 }}>{item.title}</Text>
        {/* 仅加载可见项的图片 */}
        {visibleItemIds.has(item.id) ? (
          <Image
            source={{ uri: item.imageUrl }}
            style={{ width: '100%', height: 200, borderRadius: 8 }}
            resizeMode="cover"
          />
        ) : (
          // 占位容器,可替换为骨架屏组件
          <View style={{ width: '100%', height: 200, backgroundColor: '#f5f5f5', borderRadius: 8 }} />
        )}
      </View>
    );
  };

  return (
    <FlatList
      data={posts}
      renderItem={renderPostItem}
      keyExtractor={item => item.id.toString()}
      onViewableItemsChanged={handleViewableItemsChanged}
      viewabilityConfig={viewabilityConfig.current}
      // 开启视口外组件移除,优化内存占用
      removeClippedSubviews={true}
    />
  );
};

export default PostList;

你可以根据需求调整itemVisiblePercentThreshold的值,比如设为10的话,只要帖子有10%进入视口就开始加载图片。

方案二:使用第三方懒加载库(更省心)

如果不想手动写逻辑,可以用成熟的第三方库来简化实现,比如expo-image(如果你用Expo开发的话,它自带懒加载功能),或者react-native-lazyload-image。

用expo-image实现的示例:

import { FlatList, View, Text } from 'react-native';
import { Image } from 'expo-image';

const PostList = ({ posts }) => {
  const renderPostItem = ({ item }) => {
    return (
      <View style={{ padding: 16, borderBottomWidth: 1, borderBottomColor: '#eee' }}>
        <Text style={{ fontSize: 18, marginBottom: 8 }}>{item.title}</Text>
        <Image
          source={{ uri: item.imageUrl }}
          style={{ width: '100%', height: 200, borderRadius: 8 }}
          resizeMode="cover"
          // 占位背景色,可替换为本地占位图
          placeholder={{ backgroundColor: '#f5f5f5' }}
          contentFit="cover"
          // 自动懒加载,无需额外配置
        />
      </View>
    );
  };

  return (
    <FlatList
      data={posts}
      renderItem={renderPostItem}
      keyExtractor={item => item.id.toString()}
      removeClippedSubviews={true}
    />
  );
};

expo-image会自动检测元素是否进入视口,只有当元素出现在屏幕内时才会开始加载图片,同时还支持图片缓存、渐进式加载等功能,性能表现也很出色。

额外优化建议:

  • 确保占位容器的尺寸和真实图片一致,避免图片加载时出现布局跳动
  • 配合removeClippedSubviews={true}属性,让FlatList自动移除视口外的组件,减少内存占用
  • 如果图片量很大,建议启用图片缓存,避免重复加载消耗带宽

内容的提问来源于stack exchange,提问作者David

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:24:45