模块 API 参考

编辑

Expo 模块 API 的 API 参考。


原生模块 API 是建立在 JSI 及其他 React Native 构建的低级原语之上的一个抽象层。它使用现代语言(Swift 和 Kotlin)构建,并提供一个易于使用且方便的 API,使其在可能的情况下跨平台一致。

定义组件

正如您可能在 入门 页面上的片段中注意到的,每个模块类必须实现 definition 函数。 模块定义由描述模块功能和行为的 DSL 组件组成。

名称

设置 JavaScript 代码将用于引用模块的模块名称。接受一个字符串作为参数。这可以从模块的类名推导出来,但建议为了清晰起见明确设置。

Swift / Kotlin
Name("MyModuleName")

常量

在 JavaScript 对象上定义一个常量属性。该属性仅在首次访问时计算,后续访问将返回缓存值。

Swift
Constant("PI") { Double.pi }
Kotlin
Constant("PI") { Math.PI }

函数

定义一个将导出到 JavaScript 的本机同步函数。同步意味着当函数在 JavaScript 中执行时,它的本机代码在同一线程上运行,并阻止脚本的进一步执行,直到本机函数返回。

参数

  • name: String — 您将从 JavaScript 中调用的函数名称。
  • body: (args...) -> ReturnType — 函数调用时要运行的闭包。

该函数最多可以接收 8 个参数。这是由于 Swift 和 Kotlin 中的泛型限制,因为此组件必须为每种参数数目单独实现。

有关可以在函数体中使用的类型的更多详细信息,请参见 参数类型 部分。

Swift
Function("mySyncFunction") { (message: String) in return message }
Kotlin
Function("mySyncFunction") { message: String -> return@Function message }
JavaScript
import { requireNativeModule } from 'expo-modules-core'; // 假设我们将模块命名为 "MyModule" const MyModule = requireNativeModule('MyModule'); function getMessage() { return MyModule.mySyncFunction('bar'); }

AsyncFunction

定义一个始终返回 Promise 的 JavaScript 函数,并且默认情况下其本机代码将在与 JavaScript 运行时不同的线程上调度。

参数

  • name: String — 您将从 JavaScript 中调用的函数名称。
  • body: (args...) -> ReturnType — 函数调用时要运行的闭包。

如果最后一个参数的类型是 Promise,该函数将在响应返回给 JavaScript 之前等待该 Promise 被解析或拒绝。否则,函数将立即用返回值解析或在抛出异常时拒绝。 该函数最多可以接收 8 个参数(包括 Promise)。

有关可以在函数体中使用的类型的更多详细信息,请参见 参数类型 部分。

AsyncFunction 在以下情况下更建议使用:

  • 执行 I/O 绑定任务,例如发送网络请求或与文件系统交互
  • 需要在不同线程上运行,例如,UI 相关任务的主 UI 线程
  • 是大量或长时间运行的操作,这将阻塞 JavaScript 线程,从而减少应用程序的响应性
Swift
AsyncFunction("myAsyncFunction") { (message: String) in return message } // 或 AsyncFunction("myAsyncFunction") { (message: String, promise: Promise) in promise.resolve(message) }
Kotlin
AsyncFunction("myAsyncFunction") { message: String -> return@AsyncFunction message } // 或 // 确保从 `expo.modules.kotlin` 导入 `Promise` 类,而不是 `expo.modules.core`。 AsyncFunction("myAsyncFunction") { message: String, promise: Promise -> promise.resolve(message) }
JavaScript
import { requireNativeModule } from 'expo-modules-core'; // 假设我们将模块命名为 "MyModule" const MyModule = requireNativeModule('MyModule'); async function getMessageAsync() { return await MyModule.myAsyncFunction('bar'); }

可以通过在该组件的结果上调用 .runOnQueue 函数来更改 AsyncFunction 的本机队列。

Swift
AsyncFunction("myAsyncFunction") { (message: String) in return message }.runOnQueue(.main)
Kotlin
AsyncFunction("myAsyncFunction") { message: String -> return@AsyncFunction message }.runOnQueue(Queues.MAIN)

Kotlin 协程
Android

AsyncFunction 可以在 Android 上接收可挂起的主体。然而,它必须在 Coroutine 块后用中缀语法传入。您可以在 协程概述 上了解有关可挂起函数和协程的更多信息。

带有可挂起主体的 AsyncFunction 不能接收 Promise 作为参数。它使用挂起机制来执行异步调用。 函数将立即解析为提供的可挂起块的返回值,或在抛出异常时拒绝。该函数最多可以接收 8 个参数。

默认情况下,挂起函数在模块的协程范围内调度。此外,从主体块调用的每个其他可挂起函数都在同一范围内运行。 该范围的生命周期与模块的生命周期绑定 - 当模块被解除分配时,所有未完成的挂起函数将被取消。

Kotlin
AsyncFunction("suspendFunction") Coroutine { message: String -> // 您可以在此处执行其他可挂起函数。 // 例如,您可以使用 `kotlinx.coroutines.delay` 延迟解析底层 promise。 delay(5000) return@Coroutine message }

事件

定义模块可以发送到 JavaScript 的事件名称。

注意: 该组件可用在 View 块内以定义回调名称。请参见 View 回调

Swift
Events("onCameraReady", "onPictureSaved", "onBarCodeScanned")
Kotlin
Events("onCameraReady", "onPictureSaved", "onBarCodeScanned")

请参见 发送事件 了解如何从本机代码发送事件到 JavaScript/TypeScript。

属性

在表示原生模块的 JavaScript 对象上直接定义一个新属性。它与在模块对象上调用 Object.defineProperty 是相同的。

要声明只读属性,您可以使用需要两个参数的简写语法:

  • name: String — 您将从 JavaScript 使用的属性名称。
  • getter: () -> PropertyType — 当调用属性的 getter 时要运行的闭包。
Swift
Property("foo") { return "bar" }
Kotlin
Property("foo") { return@Property "bar" }

在可变属性的情况下,getter 和 setter 闭包都是必需的(使用下面的语法也可以声明仅具有 setter 的属性):

  • name: String — 您将从 JavaScript 使用的属性名称。
  • getter: () -> PropertyType — 当调用属性的 getter 时要运行的闭包。
  • setter: (newValue: PropertyType) -> void — 当调用属性的 setter 时要运行的闭包。
Swift
Property("foo") .get { return "bar" } .set { (newValue: String) in // 对新值执行某些操作 }
Kotlin
Property("foo") .get { return@get "bar" } .set { newValue: String -> // 对新值执行某些操作 }
JavaScript
import { requireNativeModule } from 'expo-modules-core'; // 假设我们将模块命名为 "MyModule" const MyModule = requireNativeModule('MyModule'); // 获取属性值 MyModule.foo; // 设置新值 MyModule.foo = 'foobar';

视图

使模块能够作为本机视图使用。视图定义中接受的定义组件:Prop, Events, GroupViewAsyncFunction

在视图定义中的 AsyncFunction 将添加到表示本机视图的 React 组件的 React 引用。 此类异步函数会自动将本机视图的实例作为第一个参数接收,默认在 UI 线程上运行。

参数

  • viewType — 将被渲染的本机视图的类。注意:在 Android 上,提供的类必须继承自 ExpoView,在 iOS 上是可选的。请参见 扩展 ExpoView
  • definition: () -> ViewDefinition — 视图定义的构建器。
Swift
View(UITextView.self) { Prop("text") { %%placeholder-start%%... %%placeholder-end%% } AsyncFunction("focus") { (view: UITextView) in view.becomeFirstResponder() } }
Kotlin
View(TextView::class) { Prop("text") { %%placeholder-start%%... %%placeholder-end%% } AsyncFunction("focus") { view: TextView -> view.requestFocus() } }

信息 支持 SwiftUI 视图的渲染尚在计划中。目前,您可以使用 UIHostingController 并将其内容视图添加到您的 UIKit 视图。

OnCreate

定义模块的生命周期监听器,该监听器在模块初始化后立即被调用。如果您需要在模块初始化时设置某些内容,请使用此方法,而不是模块的类初始化器。

OnDestroy

定义模块的生命周期监听器,该监听器在模块即将被解除分配时调用。请使用此方法取代模块的类析构函数。

OnStartObserving

定义当第一个事件监听器被添加时调用的函数。

OnStopObserving

定义当所有事件监听器被移除时调用的函数。

OnAppContextDestroys

定义模块的生命周期监听器,该监听器在拥有模块的应用上下文即将被解除分配时调用。

OnAppEntersForeground

Only for:
iOS

定义当应用即将进入前台模式时调用的监听器。

注意: 此函数在 Android 上不可用 — 您可能想要使用 OnActivityEntersForeground

OnAppEntersBackground

Only for:
iOS

定义当应用进入背景模式时调用的监听器。

注意: 此函数在 Android 上不可用 — 您可能想要使用 OnActivityEntersBackground 代替。

OnAppBecomesActive

Only for:
iOS

定义当应用再次变为活动状态时调用的监听器(在 OnAppEntersForeground 之后)。

注意: 此函数在 Android 上不可用 — 您可能想要使用 OnActivityEntersForeground

OnActivityEntersForeground

Only for:
Android

定义活动生命周期监听器,该监听器在活动恢复后立即调用。

注意: 此函数在 iOS 上不可用 — 您可能想要使用 OnAppEntersForeground 替代。

OnActivityEntersBackground

Only for:
Android

定义活动生命周期监听器,该监听器在活动暂停后立即调用。

注意: 此函数在 iOS 上不可用 — 您可能想要使用 OnAppEntersBackground 代替。

OnActivityDestroys

Only for:
Android

定义活动生命周期监听器,该监听器在拥有 JavaScript 上下文的活动即将被销毁时调用。

注意: 此函数在 iOS 上不可用 — 您可能想要使用 OnAppEntersBackground 代替。

OnActivityResult

Only for:
Android

定义活动生命周期监听器,该监听器在使用 startActivityForResult 启动的活动返回结果时调用。

参数

  • activity — 收到结果的 Android 活动。
  • payload — 一个包含活动结果数据的对象。
    • requestCode: Int — 最初提供给 startActivityForResult 的请求代码,用于识别结果的来源。
    • resultCode: Int — 子活动返回的结果代码(例如,Activity.RESULT_OKActivity.RESULT_CANCELED)。
    • data — 可选的意图,携带从启动的活动返回的结果数据。可以为 null
Kotlin
AsyncFunction('someFunc') { %%placeholder-start%%... %%placeholder-end%% activity.startActivityForResult(someIntent, SOME_REQUEST_CODE) } OnActivityResult { activity, payload -> %%placeholder-start%%... %%placeholder-end%% }

常量

警告 已弃用: 请改用 Constant

在模块上设置常量属性。可以接受字典或返回字典的闭包。

Swift
// 从字典创建 Constants([ "PI": Double.pi ]) // 或由闭包返回 Constants { return [ "PI": Double.pi ] }
Kotlin
// 作为参数传递 Constants( "PI" to kotlin.math.PI ) // 或由闭包返回 Constants { return@Constants mapOf( "PI" to kotlin.math.PI ) }

视图定义组件

视图定义由描述视图功能和行为的 DSL 组件组成。这些组件只能在 View 闭包中使用。

名称

设置 JavaScript 代码将用于引用视图的视图名称。接受一个字符串作为参数。这可以从视图的类名推导出来,但为了清晰起见建议显式设置。

Swift / Kotlin
Name("MyViewName")

Prop

定义给定名称的视图属性的 setter。

参数

  • name: String — 您希望定义 setter 的视图属性的名称。
  • defaultValue: ValueType — 当 setter 被调用时使用的可选默认值,值为 null
  • setter: (view: ViewType, value: ValueType) -> () — 在视图重新渲染时调用的闭包。

此属性只能在 View 闭包中使用。

Swift
Prop("background") { (view: UIView, color: UIColor) in view.backgroundColor = color }
Kotlin
Prop("background") { view: View, @ColorInt color: Int -> view.setBackgroundColor(color) }

具有默认值的属性定义。

Swift
Prop("background", UIColor.black) { (view: UIView, color: UIColor) in view.backgroundColor = color }
Kotlin
Prop("background", Color.BLACK) { view: View, @ColorInt color: Int -> view.setBackgroundColor(color) }

注意: 目前不支持函数类型(回调)的属性。

OnViewDidUpdateProps

定义视图生命周期方法,当视图完成更新所有属性时调用。

View(MyView.self) { OnViewDidUpdateProps { view: MyView in %%placeholder-start%%... %%placeholder-end%% } }
View(MyView::class) { OnViewDidUpdateProps { view: MyView -> %%placeholder-start%%... %%placeholder-end%% } }

(View) AsyncFunction

与模块定义中的 AsyncFunction 类似,您可以定义附加到视图引用的函数,以允许直接修改本机视图。

视图异步函数将始终在主队列上调度,并可以将视图实例作为第一个参数接收。

Swift
View(MyView.self) { AsyncFunction("myAsyncFunction") { (view: MyView, message: String) in view.displayMessage(message) } }
Kotlin
View(MyView::class) { AsyncFunction("myAsyncFunction") { view: MyView, message: String -> view.displayMessage(message); } }
JavaScript
const MyNativeView = requireNativeViewManager('MyView'); function MyComponent() { const ref = React.useRef(null); React.useEffect(() => { ref.current?.myAsyncFunction(); }, [ref]); return <MyNativeView ref={ref} />; }

GroupView

Only for:
Android

使视图能够作为视图组使用。可以在组视图定义中接受的定义组件:AddChildView, GetChildCount, GetChildViewAt, RemoveChildView, RemoveChildViewAt

参数

  • viewType — 本机视图的类。注意,提供的类必须继承自 Android ViewGroup
  • definition: () -> ViewGroupDefinition — 视图组定义的构建器。

此属性只能在 View 闭包中使用。

Kotlin
GroupView<ViewGroup> { AddChildView { parent, child, index -> %%placeholder-start%%... %%placeholder-end%%} }

AddChildView

Only for:
Android

定义将子视图添加到视图组的动作。

参数

  • action: (parent: ParentType, child: ChildType, index: Int) -> () — 将子视图添加到视图组的动作。

此属性只能在 GroupView 闭包中使用。

Kotlin
AddChildView { parent, child: View, index -> parent.addView(child, index) }

GetChildCount

Only for:
Android

定义获取视图组中子视图数量的动作。

参数

  • action: (parent: ParentType) -> Int — 返回子视图数量的函数。

此属性只能在 GroupView 闭包中使用。

Kotlin
GetChildCount { parent -> return@GetChildCount parent.childCount }

GetChildViewAt

Only for:
Android

定义从视图组中检索特定索引的子视图的动作。

参数

  • action: (parent: ParentType, index: Int) -> ChildType — 从视图组检索特定索引的子视图的函数。

此属性只能在 GroupView 闭包中使用。

Kotlin
GetChildViewAt { parent, index -> parent.getChildAt(index) }

RemoveChildView

Only for:
Android

定义从视图组中移除特定子视图的动作。

参数

  • action: (parent: ParentType, child: ChildType) -> () — 从视图组中移除特定子视图的函数。

此属性只能在 GroupView 闭包中使用。

Kotlin
RemoveChildView { parent, child: View -> parent.removeView(child) }

RemoveChildViewAt

Only for:
Android

定义从视图组中移除特定索引的子视图的动作。

参数

  • action: (parent: ParentType, child: ChildType) -> () — 从视图组中移除在特定索引的子视图的函数。

此属性只能在 GroupView 闭包中使用。

Kotlin
RemoveChildViewAt { parent, index -> parent.removeViewAt(child) }

参数类型

从根本上说,只有原始类型和可序列化数据可以在线程之间来回传递。然而,通常原生模块需要接收自定义数据结构——比只带值为未知(Any)类型的字典/映射更复杂,因此每个值必须单独验证和转换。Expo 模块 API 提供协议,使得处理数据对象更为方便,提供自动验证,最终确保每个对象成员的本机类型安全。

原始类型

所有函数和视图属性 setter 接受所有 Swift 和 Kotlin 中的公共原始类型作为参数。这包括原始类型的数组、字典/映射和可选值。

语言支持的原始类型
SwiftBool, Int, Int8, Int16, Int32, Int64, UInt, UInt8, UInt16, UInt32, UInt64, Float32, Double, String
KotlinBoolean, Int, Long, Float, Double, String, Pair

可转换类型

可转换类型 是指可以从某些特定类型的数据(从 JavaScript 接收)初始化的本机类型。这种类型可以作为 Function 主体中的参数类型使用。例如,当 CGPoint 类型作为函数参数类型使用时,其实例可以从一个包含两个数字的数组 (x, y) 或一个具有数值 xy 属性的 JavaScript 对象创建。

内置的可转换类型在 后面 中有更详细的文档。您可以通过使本机 Swift 类型符合 Convertible 协议来定义额外的可转换类型:

Convertible

Only for:
iOS

Convertible 是一个 Swift 协议,具有一个静态方法:

convert(value, appContext)

ParameterTypeDescription
valueAny?

要转换的来自 JavaScript 的值

appContextAppContext

当前运行 Expo 应用实例的上下文对象


一个将动态类型的值从 JavaScript 转换为符合 Convertible 的 Swift 类型实例的静态方法。实现者应在给定值无效或类型不受支持时抛出异常。

Returns:
Self

示例

Swift
import ExpoModulesCore extension CMTime: @retroactive Convertible { public static func convert(from value: Any?, appContext: AppContext) throws -> CMTime { if let seconds = value as? Double { return CMTime(seconds: seconds, preferredTimescale: .max) } throw Conversions.ConvertingException<CMTime>(value) } }

信息 支持使用 Kotlin 定义可转换类型计划将在 SDK 53 可用。


内置可转换类型

一些来自 CoreGraphicsUIKit 系统框架的常见 iOS 类型已经被设置为可转换。

原生 iOS 类型TypeScript
URLstring 具有 URL。当未提供方案时,假设为文件 URL。
CGFloatnumber
CGPoint{ x: number, y: number }number[] 具有 xy 坐标
CGSize{ width: number, height: number }number[] 具有 widthheight
CGVector{ dx: number, dy: number }number[] 具有 dxdy 向量差异
CGRect{ x: number, y: number, width: number, height: number }number[] 具有 x, y, widthheight
CGColor
UIColor
颜色十六进制字符串(#RRGGBB, #RRGGBBAA, #RGB, #RGBA),遵循 CSS3/SVG 规范 的命名颜色或 "transparent"
DataUint8Array
SDK 50+

同样,一些来自 java.iojava.netandroid.graphics 等包的常见 Android 类型也被设置为可转换。

注意: 在 Android 上,尽可能使用原始数组。

原生 Android 类型TypeScript
java.net.URLstring 具有 URL。请注意,必须提供方案(URL 不应包含任何未编码的 % 字符)
android.net.Uri
java.net.URI
string 具有 URI。请注意,必须提供方案(URI 不应包含任何未编码的 % 字符)
java.io.File
java.nio.file.Path(仅在 Android API 26 上可用)
string 具有文件路径
android.graphics.Color颜色十六进制字符串(#RRGGBB, #RRGGBBAA, #RGB, #RGBA),遵循 CSS3/SVG 规范 的命名颜色或 "transparent"
kotlin.Pair<A, B>包含两个值的数组,第一个值为 A 类型,第二个值为 B 类型
kotlin.ByteArrayUint8Array
SDK 50+
kotlin.BooleanArrayboolean[]
kotlin.IntArray
kotlin.FloatArray
kotlin.LongArray
kotlin.DoubleArray
number[]
kotlin.time.Durationnumber 表示持续时间(秒)
SDK 52+

记录

记录 是可转换类型,是字典(Swift)或映射(Kotlin)的等价物,但表示为一个结构体,每个字段可以具有其类型并提供默认值。 它是表示具有本机类型安全的 JavaScript 对象的更好方式。

Swift
struct FileReadOptions: Record { @Field var encoding: String = "utf8" @Field var position: Int = 0 @Field var length: Int? } // 现在该记录可以用作函数或视图属性 setter 的参数。 Function("readFile") { (path: String, options: FileReadOptions) -> String in // 使用给定的 `options` 读取文件 }
Kotlin
class FileReadOptions : Record { @Field val encoding: String = "utf8" @Field val position: Int = 0 @Field val length: Int? = null } // 现在该记录可以用作函数或视图属性 setter 的参数。 Function("readFile") { path: String, options: FileReadOptions -> // 使用给定的 `options` 读取文件 }

枚举

使用枚举,我们可以更进一步,限制上述示例(使用 FileReadOptions 记录)支持的编码为 "utf8""base64"。要使用枚举作为参数或记录字段,它必须表示原始值(例如,StringInt),并遵循 Enumerable

Swift
enum FileEncoding: String, Enumerable { case utf8 case base64 } struct FileReadOptions: Record { @Field var encoding: FileEncoding = .utf8 %%placeholder-start%%... %%placeholder-end%% }
Kotlin
// 注意:构造函数必须带有一个名为 value 的参数。 enum class FileEncoding(val value: String) : Enumerable { utf8("utf8"), base64("base64") } class FileReadOptions : Record { @Field val encoding: FileEncoding = FileEncoding.utf8 %%placeholder-start%%... %%placeholder-end%% }

双重类型

有一些用例需要将不同的类型传递给单个函数参数。这时,双重类型可能会有用。 它们作为某几种类型中的一种的值的容器。

Swift
Function("foo") { (bar: Either<String, Int>) in if let bar: String = bar.get() { // `bar` 是一个字符串 } if let bar: Int = bar.get() { // `bar` 是一个整数 } }
Kotlin
Function("foo") { bar: Either<String, Int> -> bar.get(String::class).let { // `it` 是一个字符串 } bar.get(Int::class).let { // `it` 是一个整数 } }

目前提供三种双重类型的实现,允许您使用多达四种不同的子类型。

  • Either<FirstType, SecondType> — 两种类型之一的容器。
  • EitherOfThree<FirstType, SecondType, ThirdType> — 三种类型之一的容器。
  • EitherOfFour<FirstType, SecondType, ThirdType, FourthType> — 四种类型之一的容器。

JavaScript 值

也可以使用 JavaScriptValue 类型,这是一个可以表示于 JavaScript 中的任何值的持有者。 当您要修改给定参数或想要省略类型验证和转换时,此类型非常有用。 请注意,使用特定于 JavaScript 的类型限制在同步函数中,因为 JavaScript 运行时中的所有读取和写入必须在线程中进行。 从不同线程访问这些值将导致崩溃。

除了原始值外,可以使用 JavaScriptObject 类型仅允许对象类型,JavaScriptFunction<ReturnType> 用于回调。

Swift
Function("mutateMe") { (value: JavaScriptValue) in if value.isObject() { let jsObject = value.getObject() jsObject.setProperty("expo", value: "modules") } } // 或 Function("mutateMe") { (jsObject: JavaScriptObject) in jsObject.setProperty("expo", value: "modules") }
Kotlin
Function("mutateMe") { value: JavaScriptValue -> if (value.isObject()) { val jsObject = value.getObject() jsObject.setProperty("expo", "modules") } } // 或 Function("mutateMe") { jsObject: JavaScriptObject -> jsObject.setProperty("expo", "modules") }

本机类

模块

原生模块的基类。

属性

appContext

提供对 AppContext 的访问。

Returns:
AppContext

方法

sendEvent(eventName, payload)

ParameterTypeDescription
eventNamestring

JavaScript 事件的名称

payloadAndroid: Map<String, Any?> | Bundle iOS: [String: Any?]

事件有效负载


使用给定名称和有效负载将事件发送到 JavaScript。请参见 发送事件

Returns:
void

AppContext

应用上下文是单个 Expo 应用的接口。

属性

constants

提供对传统模块注册表中的应用常量的访问。

Returns:
Android: ConstantsInterface? iOS: EXConstantsInterface?

permissions

提供对传统模块注册表中的权限管理器的访问。

Returns:
Android: Permissions? iOS: EXPermissionsInterface?

imageLoader

提供对传统模块注册表中的图像加载器的访问。

Returns:
Android: ImageLoaderInterface? iOS: EXImageLoaderInterface?

barcodeScanner

提供对传统模块注册表中的条形码扫描器管理器的访问。

Returns:
ImageLoaderInterface?

camera

提供对传统模块注册表中的相机视图管理器的访问。

Returns:
CameraViewInterface?

font

提供对传统模块注册表中的字体管理器的访问。

Returns:
FontManagerInterface?

sensor

提供对传统模块注册表中的传感器管理器的访问。

Returns:
SensorServiceInterface?

taskManager

提供对传统模块注册表中的任务管理器的访问。

Returns:
TaskManagerInterface?

activityProvider

提供对传统模块注册表中的活动提供者的访问。

Returns:
ActivityProvider?

reactContext

提供对 React 应用程序上下文的访问。

Returns:
Context?

hasActiveReactInstance

检查是否存在非空且存活的 React Native 实例。

Returns:
Boolean

utilities

提供对传统模块注册表中实用工具的访问。

Returns:
EXUtilitiesInterface?

ExpoView

所有导出视图应使用的基类。

在 iOS 上,ExpoView 扩展了处理一些样式(例如边框)和可访问性的 RCTView

属性

appContext

提供对 AppContext 的访问。

Returns:
AppContext

扩展 ExpoView

要使用 View 组件导出您的视图,您的自定义类必须继承自 ExpoView。通过这样做,您将能够访问 AppContext 对象。这是与其他模块和 JavaScript 运行时通信的唯一方法。此外,您不能更改构造函数参数,因为提供的视图将由 expo-modules-core 初始化。

Swift
class LinearGradientView: ExpoView {} public class LinearGradientModule: Module { public func definition() -> ModuleDefinition { View(LinearGradientView.self) { %%placeholder-start%%... %%placeholder-end%% } } }
Kotlin
class LinearGradientView( context: Context, appContext: AppContext, ) : ExpoView(context, appContext) class LinearGradientModule : Module() { override fun definition() = ModuleDefinition { View(LinearGradientView::class) { %%placeholder-start%%... %%placeholder-end%% } } }

指南

发送事件

虽然 JavaScript/TypeScript 到本机的通信主要由本机函数覆盖,但您可能还想让 JavaScript/TypeScript 代码知道某些系统事件,例如剪贴板内容的更改。

为此,在模块定义中,您需要提供模块可以使用 Events 定义组件发送的事件名称。之后,您可以在模块实例上使用 sendEvent(eventName, payload) 函数来发送实际事件及其有效负载。例如,最小的剪贴板实现可以发送本机事件如下所示:

Swift
let CLIPBOARD_CHANGED_EVENT_NAME = "onClipboardChanged" public class ClipboardModule: Module { public func definition() -> ModuleDefinition { Events(CLIPBOARD_CHANGED_EVENT_NAME) OnStartObserving { NotificationCenter.default.addObserver( self, selector: #selector(self.clipboardChangedListener), name: UIPasteboard.changedNotification, object: nil ) } OnStopObserving { NotificationCenter.default.removeObserver( self, name: UIPasteboard.changedNotification, object: nil ) } } @objc private func clipboardChangedListener() { sendEvent(CLIPBOARD_CHANGED_EVENT_NAME, [ "contentTypes": availableContentTypes() ]) } }
Kotlin
const val CLIPBOARD_CHANGED_EVENT_NAME = "onClipboardChanged" class ClipboardModule : Module() { override fun definition() = ModuleDefinition { Events(CLIPBOARD_CHANGED_EVENT_NAME) OnStartObserving { clipboardManager?.addPrimaryClipChangedListener(listener) } OnStopObserving { clipboardManager?.removePrimaryClipChangedListener(listener) } } private val clipboardManager: ClipboardManager? get() = appContext.reactContext?.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager private val listener = ClipboardManager.OnPrimaryClipChangedListener { clipboardManager?.primaryClipDescription?.let { clip -> this@ClipboardModule.sendEvent( CLIPBOARD_CHANGED_EVENT_NAME, bundleOf( "contentTypes" to availableContentTypes(clip) ) ) } } }

要在 JavaScript/TypeScript 中订阅这些事件,请使用 addListener 对由 requireNativeModule 返回的模块对象进行处理。模块扩展了内置的 EventEmitter 类。 或者,您可以使用 useEventuseEventListener 钩子。

TypeScript
import { requireNativeModule, NativeModule } from 'expo'; type ClipboardChangeEvent = { contentTypes: string[]; }; type ClipboardModuleEvents = { onClipboardChanged(event: ClipboardChangeEvent): void; }; declare class ClipboardModule extends NativeModule<ClipboardModuleEvents> {} const Clipboard = requireNativeModule<ClipboardModule>('Clipboard'); Clipboard.addListener('onClipboardChanged', (event: ClipboardChangeEvent) => { alert('Clipboard has changed'); });

视图回调

某些事件与特定视图相关联。例如,触摸事件只应发送到被按下的底层 JavaScript 视图。在这种情况下,您不能使用 发送事件 中描述的 sendEventexpo-modules-core 引入了一种视图回调机制以处理视图绑定事件。

要使用它,在视图定义中,您需要使用 Events 定义组件提供视图可以发送的事件名称。之后,您需要在视图类中声明一个类型为 EventDispatcher 的属性。声明的属性名称必须与 Events 组件中导出的名称相同。然后,您可以将其作为函数调用,并传递类型为 [String: Any?] 的有效负载(在 iOS 上为 Map<String, Any?>

注意: 在 Android 上,可以指定有效负载类型。在类型无法转换为对象的情况下,有效负载将被封装并存储在 payload 键下:{payload: <provided value>}

Swift
class CameraViewModule: Module { public func definition() -> ModuleDefinition { View(CameraView.self) { Events( "onCameraReady" ) %%placeholder-start%%... %%placeholder-end%% } } } class CameraView: ExpoView { let onCameraReady = EventDispatcher() func callOnCameraReady() { onCameraReady([ "message": "Camera was mounted" ]); } }
Kotlin
class CameraViewModule : Module() { override fun definition() = ModuleDefinition { View(ExpoCameraView::class) { Events( "onCameraReady" ) %%placeholder-start%%... %%placeholder-end%% } } } class CameraView( context: Context, appContext: AppContext ) : ExpoView(context, appContext) { val onCameraReady by EventDispatcher() fun callOnCameraReady() { onCameraReady(mapOf( "message" to "Camera was mounted" )); } }

要在 JavaScript/TypeScript 中订阅这些事件,您需要将函数传递给本机视图,如下所示:

TypeScript
import { requireNativeViewManager } from 'expo-modules-core'; const CameraView = requireNativeViewManager('CameraView'); export default function MainView() { const onCameraReady = event => { console.log(event.nativeEvent); }; return <CameraView onCameraReady={onCameraReady} />; }

提供的有效负载可在 nativeEvent 键下使用。

示例

Swift
public class MyModule: Module { public func definition() -> ModuleDefinition { Name("MyFirstExpoModule") Function("hello") { (name: String) in return "Hello \(name)!" } } }
Kotlin
class MyModule : Module() { override fun definition() = ModuleDefinition { Name("MyFirstExpoModule") Function("hello") { name: String -> return "Hello $name!" } } }

要了解来自真实模块的更多示例,可以参考在 GitHub 上使用此 API 的 Expo 模块:

expo-batterySwift
expo-cellular

Kotlin, Swift

expo-clipboard

Kotlin, Swift

expo-crypto

Kotlin, Swift

expo-deviceSwift
expo-hapticsSwift
expo-image-manipulatorSwift
expo-image-picker

Kotlin, Swift

expo-linear-gradient

Kotlin, Swift

expo-localization

Kotlin, Swift

expo-store-reviewSwift
expo-system-uiSwift
expo-video-thumbnailsSwift
expo-web-browser

Kotlin, Swift