跳过主要内容
教程

使用纯 React.js 和 Capacitor 构建移动应用

关于如何使用 Capacitor 将 React.js 网页应用转换为原生移动应用,添加 Capgo 原生导航、过渡和 iOS 布局最佳实践的指南。

马丁·多纳迪厄

马丁·多纳迪厄

内容营销人员

使用纯 React.js 和 Capacitor 构建移动应用

本教程将指导您使用 React 和 Capacitor 构建移动应用。通过此过程,您将了解如何将 React.js 网页应用转换为原生移动应用,使用 Capacitor,并添加原生导航和过渡的 Capgo。

Capacitor 可以轻松将您的 React.js 网页应用转换为原生移动应用,无需进行重大修改或学习新的策略,如 React Native。

该过程涉及几个简单的步骤,很快您的 React.js 应用就会成为一个功能齐全的移动应用。因此,请继续阅读本教程,了解如何将您的应用转换为移动应用。

Capacitor 简介

CapacitorJS 是一个革命性的技术。它可以无缝地与任何 web 项目集成,并将您的应用程序包装在一个本机 webview 中,同时生成 Xcode 和 Android Studio 项目。通过其插件,您可以通过 JS 桥访问本机设备功能,如摄像头。

Capacitor 提供了一种简单的方式来创建一个本机移动应用程序,无需任何麻烦或陡峭的学习曲线。其简单的 API 和流线化的功能使其易于在您的项目中集成。

设置您的 React.js 应用程序

让我们使用最简单的方法来启动一个 React 应用程序。我们将使用 npm 包管理器创建一个新的 React 应用程序:

npx create-react-app my-app

将我们的项目转换为本机移动应用程序所需的 export 我们的应用程序。

我们将在下一刻回来。首先,让我们了解如何将 Capacitor 集成到我们的 React 应用程序中。

将 Capacitor 集成到您的 React.js 应用程序

初始设置步骤可能会有点详细,但之后更新您的本机应用程序包装器就像运行一个 sync 命令

一样。首先,我们将安装 Capacitor CLI 作为开发依赖项,并在我们的项目中设置它。在设置过程中,按“enter”键接受默认值即可。

接下来,我们将安装核心包和iOS和Android平台相关的包。

最后,我们将添加平台,Capacitor将在项目根目录创建每个平台的文件夹:

# Install the Capacitor CLI locally
npm install -D @capacitor/cli

# Initialize Capacitor in your React project
npx cap init

# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android

# Add the native platforms
npx cap add ios
npx cap add android

The iosandroid 目录现在出现在您的React.js项目中。

要访问Android项目,稍后安装 Android Studio。对于iOS,您需要一台Mac,并应安装 Xcode.

webDir 在您的 capacitor.config.json 文件如下所示:

{
  "appId": "com.example.app",
  "appName": "my-app",
  "webDir": "build",
  "bundledWebRuntime": false
}

运行构建命令并将您的项目与 Capacitor: 同步

npm run build
npx cap sync

The npm run build 命令将构建您的 React.js 项目,而 npx cap sync 将使 web code 在 native 平台的准确位置以便在应用中执行。

现在,幸运且无错误,您的 React.js 应用应该已准备好在设备上发布!

构建和部署您的原生应用

开发 iOS 应用需要 Xcode需要在 iOS 和 Android 上发布应用时,必须加入 Apple Developer Program 和 Google Play Console。 Android Studio如果您打算在应用商店发布应用,必须加入 Apple Developer Program 和 Google Play Console。

Capacitor CLI 简化了打开两个本机项目的过程:

npx cap open ios
npx cap open android

一旦您的本机项目设置完成,部署应用到连接设备就是一个简单的过程。

对于 Android Studio,等待所有内容加载完成,然后将应用部署到连接设备。

对于 Xcode,建立您的签名账户以将应用部署到真实设备,而不是仅仅使用模拟器。完成后,只需点击播放即可在连接设备上运行应用,您可以在顶部选择。

如果一切顺利,您将将您的 React.js 网页应用转换为本机移动应用!

Capacitor Live Reload

现代开发框架通常带有热重载功能,幸运的是,您可以在 Capacitor 上实现相同的功能,但 在您的移动设备上!

您可以通过让 Capacitor 应用从特定 URL 加载内容来使您的本地托管应用在您的网络上可访问并具有实时重载功能。

首先,确定您的本地 IP 地址。 在 Mac 上,您可以通过在终端中运行 ipconfig getifaddr en0 在 Windows 上执行 ipconfig 并查找 IPv4 地址。

After this, instruct Capacitor to load the app directly from the server by adding another parameter to your capacitor.config.ts 以将这些更改应用到我们的本机项目。

import { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.app',
  appName: 'my-app',
  webDir: 'build',
  bundledWebRuntime: false,
  server: {
    url: 'http://192.168.x.xx:3000',
    cleartext: true
  }
};

export default config;

在通过 Android Studio 或 Xcode 部署应用程序后,您的 React 应用程序中的任何更改都将自动重新加载并在您的应用程序中显示! npx cap copy 请记住,如果安装了新插件,例如相机,则需要重新构建您的本机项目。这是因为本机文件已更改,并且无法在实时更新。

使用 Capgo 插件

让我们快速了解如何使用 Capgo 插件。让我们安装一个简单的插件,分享插件

Using Capacitor Plugins

Let’s take a quick look at how to use a Capacitor plugin. Let’s install a simple one, the 让我们快速了解如何使用 Capgo 插件。让我们安装一个简单的插件,分享插件,触发原生分享对话框:

npm i @capacitor/share

要使用它,需要导入包并从我们的应用中调用相应的函数。考虑到 share() App.js 安装新插件后,请记住再次同步您的React项目使用:

import { Share } from '@capacitor/share';

function ShareButton() {
  const share = async () => {
    await Share.share({
      title: 'React App',
      text: 'Visit this React App',
      url: 'http://localhost:3000',
      dialogTitle: 'Share with...'
    });
  };

  return (
    <button onClick={share}>
      Share
    </button>
  );
}

export default ShareButton;

接下来,您可以使应用在iOS和Android上感觉更原生,使用__CAPGO_KEEP_0__导航和过渡,并解决常见的iOS布局问题,例如水平溢出或裁切安全区域。 npx cap sync.

原生感知UI与Capgo原生导航和过渡

Native-feeling UI with Capgo Native Navigation and Transitions

Ionic 构建跨平台应用,但将其与React集成起来很hacky,并且当您已经有 Tailwind CSS 在React + __CAPGO_KEEP_0__应用中,使用__CAPGO_KEEP_1__插件而不是仅web UI套件,如Konsta UI:.

To use it, import the package and call the respective function from our app. Consider the App.js file. After installing a new plugin, remember to sync your React project again using the CLI. Next, you can make the app feel more native on iOS and Android with Capacitor navigation and transitions, and fix common iOS layout issues that cause horizontal overflow or cropped safe areas. Native-feeling UI with Capacitor Native Navigation and Transitions. I’ve worked for years with Ionic to build cross-platform applications, but integrating it with React is hacky and rarely worth it when you already have Tailwind CSS. For a native mobile feel in a React + Capacitor app, use Capgo plugins instead of web-only UI kits like Konsta UI:

  • @capgo/capacitor-native-导航 — iOS 中使用 Liquid Glass 的标签栏,Android 中使用模糊的标签栏样式。您的 React 路由保持路由状态;插件拥有本地浏览器。
  • @capgo/capacitor-过渡 — 在 WebView层中实现Ionic风格的页面过渡和iOS的边缘滑动返回,未采用Ionic UI。

安装两者:

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

使用 CSS inset 模式配置本地导航,以便网页内容尊严本地栏:

import { NativeNavigation } from '@capgo/capacitor-native-navigation';

await NativeNavigation.configure({
  contentInsetMode: 'css',
  animationDuration: 360,
  glass: {
    effect: 'liquidGlass',
  },
});

渲染一个 Liquid Glass 的标签栏(iOS 使用系统渲染;Android 使用模糊的 WebView 背景):

await NativeNavigation.setTabbar({
  selectedId: 'home',
  labelVisibilityMode: 'labeled',
  icons: true,
  colors: { dynamic: true },
  tabs: [
    { id: 'home', title: 'Home', icon: { svg: '...' } },
    { id: 'settings', title: 'Settings', icon: { svg: '...' } },
  ],
});

await NativeNavigation.addListener('tabSelect', ({ id }) => {
  navigate(`/${id}`);
});

在应用壳中添加本地页面过渡:

import { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/react';

initTransitions({ platform: 'auto' });

export function AppShell() {
  const navigate = useNavigate();
  const outletRef = useRef<HTMLElement>(null);

  useEffect(() => {
    if (outletRef.current) {
      setupRouterOutlet(outletRef.current, { platform: 'auto', swipeGesture: 'auto' });
    }
  }, []);

  const openSettings = () => {
    setDirection('forward');
    navigate('/settings');
  };

  return <cap-router-outlet ref={outletRef}>{/* routes */}</cap-router-outlet>;
}

将路由页面包裹在 cap-router-outlet, cap-page, cap-content,并调用 setDirection('forward')setDirection('back') 在导航之前。不要在原生导航拥有这些表面的情况下重复web头部或底部。

查看完整指南: 使用@capgo/capacitor-原生导航使用@capgo/capacitor-过渡.

安全区域与Tailwind

在Tailwind CSS中使用设备安全区域,请使用 @capgo/tailwind-capacitor (发布于 tailwind-capacitor npm)。它提供 safe-areas 工具和其他Capacitor友好的Tailwind插件:

bun add -D tailwind-capacitor

src/index.css:

@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";

使用工具,如 pt-safe, pb-safepx-safe ,来代替手动添加 env(safe-area-inset-*) 。该项目正在积极开发中 — 如果您的React设置中缺少某些功能, 在GitHub上打开一个PR.

iOS布局问题(视口、安全区域和水平溢出)

如果内容在iOS上被裁切、偏移或水平滚动,仅添加或调整视口标签通常无法解决问题。按照以下顺序检查这些问题。 overflow-x: hidden 确保视口元标签已正确应用

中添加视口元标签 index.html inside <head>:

<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />

从根包装器中处理iOS安全区域

在单个应用壳中创建并应用安全区域填充 — 不在多个嵌套组件中:

html,
body,
#root {
  width: 100%;
  min-height: 100%;
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

* {
  box-sizing: border-box;
}

.app-shell {
  min-height: 100dvh;
  width: 100%;
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

将所有页面内容包裹在 .app-shell。在头部、模态窗口和布局包装器中重复应用安全区域填充,通常会使界面看起来被裁剪或过大。

使用 @capgo/tailwind-capacitor,您可以使用类似于 pt-safe pb-safe px-safe 的工具表达相同的填充。

将Capacitor iOS contentInset 设置为 never 首选

,禁用原生 inset 并让 CSS (或 Native Navigation 的 capacitor.config.ts来处理 contentInsetMode: 'css'控制安全区域:

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'build',
  ios: {
    contentInset: 'never',
  },
};

混合Capacitor的自动内容内边距与CSS env(safe-area-inset-*) 使用CSS内边距是引起双倍间距的常见原因。

找到真正溢出的元素

通常的原因是使用 100vw, Tailwind w-screen, 或一个较大的 min-width.

在Safari Web Inspector中运行:

[...document.querySelectorAll('*')]
  .filter(el => el.scrollWidth > document.documentElement.clientWidth)
  .map(el => ({
    el,
    tag: el.tagName,
    class: el.className,
    scrollWidth: el.scrollWidth,
    clientWidth: document.documentElement.clientWidth,
  }));

使用Tailwind时,替换 w-screenw-full 当可能时,许多水平溢出问题来自 100vw / w-screen, 或一个固定宽度的容器,而不是视口元标签本身。

__CAPGO_KEEP_0__

Capacitor offers a seamless means of building native apps based on an existing web project, providing a simple way to share code and have consistent UI.

Thanks to technologies like Capacitor, building mobile applications from React.js web apps has never been easier. Take your web development skills to the next level by crafting impressive native mobile apps. Happy coding!

For more about how you can fast-track your app development process, sign up for a free account today.

Keep going from Building Mobile Apps with Pure React.js and Capacitor

If you are using Building Mobile Apps with Pure React.js and Capacitor to plan native media and interface behavior, connect it with Using @capgo/capacitor-live-activities capgo offers a seamless means of building native apps based on an existing web project, providing a simple way to share capacitor and have consistent UI. @capgo/capacitor-live-activities 为capgo/capacitor-live-activities的实现细节 使用capgo/capacitor-live-activities 为capgo/capacitor-live-activities的原生能力 capgo/capacitor-live-activities 为capgo/capacitor-live-activities的实现细节, 使用capgo/capacitor-native-navigation 为capgo/capacitor-native-navigation的原生能力

Capacitor 应用程序的实时更新

当 web-layer bug 活动时,通过 Capgo 将修复推送到应用商店,而不是等待几天的审批。用户在后台接收更新,而本机更改保持在正常审批路径中。

立即开始

最新博客文章

Capgo 为您提供创建真正专业的移动应用所需的最佳见解。