如何使用 Expo Router 在 React Native 中的多个选项卡之间共享单个 WebView 实例

问题描述 投票:0回答:1

我正在开发一个 React Native 移动应用程序,使用 Expo Router 进行导航。

该应用程序的大部分功能都是作为我也构建的网站的网络包装器。不过,我正在本机实现一些功能,其中之一就是导航。

为了处理本机应用程序和 Web 应用程序之间的通信,每当本机导航事件发生时,我都会使用

postMessage
向 Web 应用程序发送消息。

我的应用程序包括 4 个底部选项卡,导航的文件夹结构如下所示:

- app
   - (tabs)
       - _layout.tsx
       - tab1.tsx
       - tab2.tsx
       - tab3.tsx
       - tab4.tsx
  • tab1、tab2 和 tab3 显示加载 Web 应用程序的
    WebView
    组件。
  • tab4 显示本机屏幕。

我想根据所选选项卡(tab1、tab2 或 tab3)导航到

WebView
中加载的 Web 应用程序的不同页面。我想在 tab4 中显示一个带有一些 React Native 组件的
View

问题:

每当我在 tab1、tab2 或 tab3 之间切换时,都会创建 WebView 的新实例。这会导致网站在我第一次选择选项卡时重新加载。我需要一种方法来跨这些选项卡共享 WebView 的单个实例,以便在切换选项卡时不会重新加载。

这是初始(选项卡)

_layout.tsx

import { theme } from "@modules/core/theme";
import { NavHeader } from "@modules/navigation/components";
import { Tabs } from "expo-router";
import React from "react";
import { Platform, Text } from "react-native";

const TabLayout = () => {
  return (
    <Tabs
      screenOptions={{
        tabBarActiveTintColor: "blue",
        tabBarStyle: Platform.select({
          ios: {
            position: "absolute",
            backgroundColor: theme.colors.backgroundDark,
          },
          default: {
            backgroundColor: theme.colors.backgroundDark,
          },
        }),
        header: () => <NavHeader />,
      }}
    >
      <Tabs.Screen
        name="tab1"
        options={{
          tabBarLabel: ({ focused }) => <Text>tab1</Text>,
        }}
      />
      <Tabs.Screen
        name="tab2"
        options={{
          tabBarLabel: ({ focused }) => <Text>tab2</Text>,
        }}
      />
      <Tabs.Screen
        name="tab3"
        options={{
          tabBarLabel: ({ focused }) => <Text>tab3</Text>,
        }}
      />
      <Tabs.Screen
        name="tab4"
        options={{
          tabBarLabel: ({ focused }) => <Text>tab4</Text>,
        }}
      />
    </Tabs>
  );
};

export default TabLayout;

这是每个选项卡内的初始代码。

tab1.tsx

import WebView from "react-native-webview";

const Tab1Route = () => {
  return <WebView source={{ uri: "https://www.mywebsite.com/tab1" }} />;
};

export default Tab1Route;

tab2.tsx

import WebView from "react-native-webview";

const Tab2Route = () => {
  return <WebView source={{ uri: "https://www.mywebsite.com/tab2" }} />;
};

export default Tab2Route;

tab3.tsx

import WebView from "react-native-webview";

const Tab3Route = () => {
  return <WebView source={{ uri: "https://www.mywebsite.com/tab3" }} />;
};

export default Tab3Route;

tab4.tsx

import { Text, View } from "react-native";

const Tab4Route = () => {
  return (
    <View>
      <Text>Tab4 screen</Text>
    </View>
  );
};

export default Tab4Route;

我尝试过的:

  • 渲染

    WebView
    文件中的
    (tabs)/_layout.tsx
    以在选项卡之间共享。我将
    Tabs
    组件包裹在
    View
    中,并将
    Webview
    放在选项卡顶部。然而,这导致了一个奇怪的 UI 问题:标题和选项卡之间的内容垂直分为两半。上半部分显示
    WebView
    ,而下半部分是空白的,直到我导航到 tab4(具有本机视图的那个),此时它会显示该 tab4 的正确内容。

  • Context API:将应用程序包装在

    Provider
    中,并为每个选项卡中的
    ref
    组件共享相同的
    WebView
    。但这没有用。当我第一次打开任何选项卡时,仍然会创建一个新实例。

  • 使用

    Portal
    在组件树中的更高级别渲染
    WebView
    组件,并有条件地在每个选项卡中显示它。但是,这也会导致在切换选项卡时创建一个新实例。我使用了 react-native-portals

我需要一种方法来确保 tab1、tab2 和 tab3 使用相同的 WebView 实例,以便在这些选项卡之间切换时网站不会重新加载。

有人有使用 Expo Router 在 React Native 中实现此目的的解决方案吗?

react-native webview react-navigation-bottom-tab expo-router shared-webview
1个回答
0
投票

共享单个 WebView 实例的步骤:

  • 创建集中式 WebView 组件

  • 创建一个共享 WebViewManager 组件,用于保存 WebView 实例并管理其状态。

  • 使用全局状态管理解决方案

  • 使用状态管理库(如 zustand 或 context)来管理 WebView 的状态及其应加载的 URL。

  • 将共享WebView嵌入到更高级别的组件中 使用 Expo Router 的选项卡导航时,在共享布局或包装器中渲染 WebView 组件。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.