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

如何让React Native的WebView在离线状态下仍可正常显示?

React Native WebView 在线/离线内容切换方案

针对你的需求,这里提供一个简单易懂的实现方案,不需要复杂依赖,适合新手:

步骤1:安装必要依赖

我们需要两个基础库:

  • 检测网络状态:@react-native-community/netinfo
  • 本地缓存内容:@react-native-async-storage/async-storage

执行安装命令:

npm install @react-native-community/netinfo @react-native-async-storage/async-storage

iOS项目需要额外执行:

cd ios && pod install && cd ..

步骤2:完整实现代码

替换你的App.js内容为以下代码,注释里有详细说明:

import React, { useState, useEffect, useRef } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import WebView from 'react-native-webview';
import NetInfo from '@react-native-community/netinfo';
import AsyncStorage from '@react-native-async-storage/async-storage';

// 配置远程URL和缓存键名
const REMOTE_URL = 'https://wikipedia.org';
const CACHE_STORAGE_KEY = 'cached_web_page';

function App() {
  // 网络状态:true为在线,false为离线
  const [isOnline, setIsOnline] = useState(true);
  // 缓存的网页内容
  const [cachedHtml, setCachedHtml] = useState('');
  // WebView实例引用
  const webViewRef = useRef(null);

  // 初始化:监听网络状态 + 加载缓存内容
  useEffect(() => {
    // 监听网络变化
    const unsubscribe = NetInfo.addEventListener(state => {
      setIsOnline(!!state.isConnected);
    });

    // 从本地加载缓存的网页
    const loadCachedContent = async () => {
      const savedHtml = await AsyncStorage.getItem(CACHE_STORAGE_KEY);
      if (savedHtml) setCachedHtml(savedHtml);
    };
    loadCachedContent();

    // 组件卸载时取消监听
    return unsubscribe;
  }, []);

  // 缓存网页内容到本地
  const saveWebContent = async (html) => {
    try {
      await AsyncStorage.setItem(CACHE_STORAGE_KEY, html);
      setCachedHtml(html);
    } catch (err) {
      console.log('缓存失败:', err);
    }
  };

  return (
    <View style={styles.container}>
      {isOnline ? (
        // 在线状态:加载远程URL,同时缓存内容
        <WebView
          ref={webViewRef}
          style={styles.webview}
          source={{ uri: REMOTE_URL }}
          // 网页加载完成后,注入JS获取HTML内容
          onLoadEnd={() => {
            webViewRef.current?.injectJavaScript(`
              window.ReactNativeWebView.postMessage(document.documentElement.outerHTML);
              true; // 必须返回true,否则JS注入会失败
            `);
          }}
          // 接收网页返回的HTML并缓存
          onMessage={(event) => {
            saveWebContent(event.nativeEvent.data);
          }}
        />
      ) : cachedHtml ? (
        // 离线状态:加载缓存的HTML内容
        <WebView
          style={styles.webview}
          source={{ html: cachedHtml }}
        />
      ) : (
        // 离线且无缓存时的占位提示
        <View style={styles.offlineTip}>
          <Text>离线状态且无缓存内容,请联网后重试</Text>
        </View>
      )}
    </View>
  );
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
  },
  webview: {
    flex: 1,
  },
  offlineTip: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    padding: 20,
    textAlign: 'center',
  },
});

export default App;

关键逻辑说明

  1. 网络状态监听:通过NetInfo实时检测设备是否联网,自动切换WebView的加载源
  2. 在线缓存:网页加载完成后,注入JavaScript获取完整HTML内容,用AsyncStorage保存到本地
  3. 离线加载:离线时优先读取本地缓存的HTML,没有缓存则显示提示

注意事项

  • AsyncStorage有大小限制(约5MB),如果网页过大可能无法缓存,后续可改用react-native-fs存储文件
  • 缓存的HTML仅包含网页结构,远程的CSS/JS/图片等静态资源离线时无法加载,若需完全离线可用,需要额外缓存静态资源(这部分较复杂,新手可先实现基础功能)
  • iOS需在Info.plist中添加网络权限,Android需在AndroidManifest.xml中添加网络权限(默认创建项目时已包含)

内容的提问来源于stack exchange,提问作者pa-one

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:05:10