教程:创建内联模块

关于如何在你的 Expo 项目中使用内联模块直接创建原生模块和视图的教程。


For the complete documentation index, see llms.txt. Use this file to discover all available pages.

警告 内联模块是实验性的。API 可能会有破坏性更改。

在本教程中,你将使用内联模块直接在你的 Expo 项目的 app 目录中创建一个示例原生模块和原生视图。 与标准的 Expo 模块不同,内联模块不需要单独的包或 create-expo-module 脚手架。 你可以将 Kotlin 和 Swift 文件与应用代码一起编写,Expo 会自动发现它们。

🌐 In this tutorial, you will create an example native module and a native view directly inside your Expo project's app directory using inline modules. Unlike the standard Expo Modules, inline modules don't require a separate package or create-expo-module scaffolding. You write Kotlin and Swift files alongside your app code, and Expo discovers them automatically.

1

设置你的项目

🌐 Setup your project

打开 应用配置 并将 expo.experiments.inlineModules.watchedDirectories 设置为 ["app"]

🌐 Open the app config and set the expo.experiments.inlineModules.watchedDirectories to ["app"]:

app.json
{ "expo": { "experiments": { "inlineModules": { "watchedDirectories": ["app"] } } } }

定义 expo.experiments.inlineModules 可以在 Expo 项目中启用内联模块功能。

🌐 Defining expo.experiments.inlineModules enables inline modules functionalities in an Expo project.

expo.experiments.inlineModules.watchedDirectories 中,你可以指定你的内联模块所在的目录。请注意,并非所有目录都被允许。更多信息,请参阅 内联模块参考

🌐 In expo.experiments.inlineModules.watchedDirectories you can specify in which directories your inline modules live. Note that not all directories are allowed. For more information, see the inline modules reference.

2

运行预构建

🌐 Run prebuild

运行预构建命令以使用内联模块设置生成 AndroidiOS 原生项目。

🌐 Run the prebuild command to generate android and ios native projects with the inline modules setup.

Terminal
npx expo prebuild

3

创建一个内联模块

🌐 Create an inline module

对于 Android,在 app 目录下创建一个名为 FirstInlineModule.kt 的 Kotlin 文件,并添加类似于以下的模块:

🌐 For Android, create a Kotlin file called FirstInlineModule.kt inside the app directory and add a module similar to the following:

app/FirstInlineModule.kt
package app import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition class FirstInlineModule : Module() { override fun definition() = ModuleDefinition { Constant("Hello") { -> "Hello Android inline modules!" } } }

对于 iOS,在 app 目录中创建一个名为 FirstInlineModule.swift 的 Swift 文件:

🌐 For iOS, create a Swift file called FirstInlineModule.swift inside the app directory:

app/FirstInlineModule.swift
internal import ExpoModulesCore class FirstInlineModule: Module { public func definition() -> ModuleDefinition { Constant("Hello") { return "Hello iOS inline modules!" } } }

4

在你的应用中使用该模块

🌐 Use the module in your app

在你应用的 TypeScript/JavaScript 代码中,你可以按以下方式使用该模块:

🌐 In your app's TypeScript/JavaScript code you can use the module in the following way:

app/index.tsx
import { requireNativeModule } from 'expo'; import { Text } from 'react-native'; const FirstInlineModule = requireNativeModule('FirstInlineModule'); export default function InlineModulesDemoComponent() { return <Text> {FirstInlineModule.Hello} </Text>; }

现在,你可以运行示例应用:

🌐 Now, you can run the example app:

Terminal
# Run the example app on Android
npx expo run:android

# Run the example app on iOS
npx expo run:ios

在运行上述命令后,你将看到应用中来自原生 Android/iOS 模块的文本常量。

🌐 After running the above command(s), you will see the app with text constant coming from the native android/iOS module.

5

创建本地视图

🌐 Create a native view

要在 app 目录中创建本地视图,让我们使用 ExpoWebView 示例。

🌐 To create a native view inside the app directory, let's use the ExpoWebView example.

对于 Android,在 app 目录下创建一个名为 FirstInlineView.kt 的 Kotlin 文件,并添加类似于以下的视图:

🌐 For Android, create a Kotlin file called FirstInlineView.kt inside the app directory and add a view similar to the following:

app/FirstInlineView.kt
package app import expo.modules.kotlin.modules.Module import expo.modules.kotlin.modules.ModuleDefinition import java.net.URL import android.content.Context import android.webkit.WebView import android.webkit.WebViewClient import expo.modules.kotlin.AppContext import expo.modules.kotlin.viewevent.EventDispatcher import expo.modules.kotlin.views.ExpoView class FirstInlineView : Module() { override fun definition() = ModuleDefinition { View(ExpoWebView::class) { Events("onLoad") Prop("url") { view: ExpoWebView, url: URL? -> view.webView.loadUrl(url.toString()) } } } } class ExpoWebView(context: Context, appContext: AppContext) : ExpoView(context, appContext) { private val onLoad by EventDispatcher() internal val webView = WebView(context).also { it.layoutParams = LayoutParams( LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT ) it.webViewClient = object : WebViewClient() { override fun onPageFinished(view: WebView, url: String) { onLoad(mapOf("url" to url)) } } addView(it) } }

对于 iOS,在 app 目录中创建一个名为 FirstInlineView.swift 的 Swift 文件:

🌐 For iOS, create a Swift file called FirstInlineView.swift inside the app directory:

app/FirstInlineView.swift
internal import ExpoModulesCore import WebKit class FirstInlineView: Module { public func definition() -> ModuleDefinition { View(ExpoWebView.self) { Events("onLoad") Prop("url") { (view, url: URL) in if view.webView.url != url { let urlRequest = URLRequest(url: url) view.webView.load(urlRequest) } } } } } class ExpoWebView: ExpoView, WKNavigationDelegate { let webView = WKWebView() let onLoad = EventDispatcher() required init(appContext: AppContext? = nil) { super.init(appContext: appContext) clipsToBounds = true webView.navigationDelegate = self addSubview(webView) } override func layoutSubviews() { webView.frame = bounds } func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { if let url = webView.url { onLoad([ "url": url.absoluteString ]) } } }

6

在你的应用中使用本地视图

🌐 Use the native view in your app

你以类似于内联模块的方式使用内联视图:

🌐 You use the inline view in a similar way to the inline module:

app/index.tsx
import { requireNativeModule, requireNativeView } from 'expo'; import { StyleSheet, Text, View } from 'react-native'; const FirstInlineModule = requireNativeModule('FirstInlineModule'); const FirstInlineView = requireNativeView('FirstInlineView'); export default function InlineModulesDemoComponent() { return ( <> <View style={styles.textBox}> <Text style={styles.text}> {FirstInlineModule.Hello} </Text> </View> <FirstInlineView style={styles.inlineView} url="https://expo.nodejs.cn/modules/" /> </> ); } const styles = StyleSheet.create({ textBox: { height: 100, justifyContent: 'flex-end', alignItems: 'center' }, text: { fontSize: 26 }, inlineView: { flex: 1 }, });

现在通过使用 npx expo run:androidnpx expo run:ios 命令编译来运行你的示例应用。

🌐 Now run your example app by compiling it using npx expo run:android or npx expo run:ios command.

运行上述命令后,你将看到应用,其中包含来自原生 Android/iOS 模块的文本常量,以及来自原生视图的 Web 视图。

🌐 After running the above command(s), you will see the app with a text constant coming from the native android/iOS module and a web view coming from a native view.

恭喜!你已经创建了你的第一个 Expo 内联模块和视图。

🌐 Congratulations! You've created your first Expo inline module and view.

下一步

🌐 Next steps

Expo 内联模块参考

关于如何使用 Kotlin 和 Swift 创建内联模块的参考资料。

教程:创建原生视图

关于使用 Expo Modules API 创建保留设置的原生模块的教程。