This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

教程:创建内联模块

编辑页面

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


在本教程中,你将使用内联模块直接在 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 内联模块!" } } }

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

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

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 持久化设置的原生模块的教程。