教程:创建内联模块

编辑页面

通过内联模块在你的 Expo 项目中直接创建原生模块和视图的教程。


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

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

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

1

设置你的项目

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

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

定义 expo.experiments.inlineModules 会为 Expo 项目启用内联模块功能。

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

2

运行 prebuild

运行 prebuild 命令以生成带有内联模块设置的 androidios 原生项目。

Terminal
npx expo prebuild

3

创建一个内联模块

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

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 文件:

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

4

在你的应用中使用该模块

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

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>; }

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

Terminal
# 在 Android 上运行示例应用
npx expo run:android

# 在 iOS 上运行示例应用
npx expo run:ios

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

5

创建一个原生视图

要在 app 目录中创建一个原生视图,我们来使用 ExpoWebView 示例。

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

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 文件:

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

在你的应用中使用原生视图

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

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://docs.expo.dev/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 命令编译并运行你的示例应用。

运行以上命令后,你将看到应用中显示来自原生 android/iOS 模块的文本常量,以及来自原生视图的网页视图。

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

下一步

Expo 内联模块参考

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

教程:创建原生模块

关于创建一个使用 Expo Modules API 持久化设置的原生模块的教程。