在 Expo 中使用 Native 组件

目前，较为流行的 React Native 框架是 Expo，Expo 提供了 Expo Modules API 可供我们快速的开发一个 Native 组件或者模块。

这篇文章将简单介绍如何在 Expo ~52 中在当前项目中初始化并编写一个简单的 Native 组件。

准备

开始之前，确保你已经建立了一个 Expo 的项目。

然后，通过以下命令创建一个 Expo Module。

Copy
npx create-expo-module@latest --local

根据引导创建了一个 Module。位于 modules/<name> 下，并存在以下的文件。

Copy
.
├── android
│ ├── build.gradle
│ └── src
│ └── main
│ ├── AndroidManifest.xml
│ └── java
│ └── expo
│ └── modules
│ └── testmodule
│ ├── TestModule.kt
│ └── TestModuleView.kt
├── expo-module.config.json
├── index.ts
├── ios
│ ├── TestModule.podspec
│ ├── TestModule.swift
│ └── TestModuleView.swift
└── src
├── TestModule.ts
├── TestModule.types.ts
├── TestModule.web.ts
├── TestModuleView.tsx
└── TestModuleView.web.tsx

10 directories, 14 files

其中，android 和 ios 目录是编写 native 代码的入口。

集成到现有项目中

现在我们需要把这种模块应用到当前的 app 中。

编辑 package.json 增加这个字段：

Copy
"expo": {
"autolinking": {
"nativeModulesDir": "./modules"
}
},

然后，执行 npm run expo prebuild --clean 刷新 ios 和 android 的项目。

等待安装完 native 依赖之后，我们使用 Xcode 打开 xcworkspace 文件。

编写一个简易模块

在初始模板中已经存在了一个官方实例模块。我们也可以尝试自己写一个简单的组件。下面以 iOS 平台并使用 Swift UI 编写。

根据图示找到我们的模块位置。

新建一个内部模块，用以下的方式组织文件：

Copy
../ListView
├── ListView.swift
└── ListViewModule.swift

在 ListView.swift 中编写以下代码，一个简单 SwiftUI List：

Copy
import SwiftUI

struct ListView: View {
var body: some View {
List {
ForEach(1...10, id: \.self) { index in
Text("\(index)")
}
}
}
}

#Preview {
ListView()
}

然后定义 Expo Module，编辑 ListViewModule.swift

Copy
import ExpoModulesCore
import SwiftUI

class ListViewProps: ExpoSwiftUI.ViewProps {

}

fileprivate struct ListViewExpoView: ExpoSwiftUI.View {
@EnvironmentObject var props: ListViewProps
var body: some View {
ListView()
}
}

public class ListViewModule: Module {
public func definition() -> ModuleDefinition {
Name("ListView") // 代表之后调用 requireNativeView 使用的标识符

View(ListViewExpoView.self) // 使用 ListViewExpoView
}
}

到这里，native 侧已经完成了。接下来修改 expo-module.config.json

增加刚刚新增的 ListViewModule。

Copy
{
"platforms": [
"apple",
"android",
"web"
],
"apple": {
"modules": [
"TestModule",
"ListViewModule" // 增加
]
},
"android": {
"modules": [
"expo.modules.testmodule.TestModule"
]
}
}

由于我们没有实现 android，这里就不写了。然后执行 npm expo prebuild。

在 React Native 中使用 Native 组件

经过了上面的步骤，下面在 React Native 中这样使用它。

Copy
import { requireNativeView } from 'expo'
import type { ViewProps } from 'react-native'

interface ListViewProps extends ViewProps {}
const ListView = requireNativeView<ListViewProps>('ListView') // 使用上面定义的 Name
export default function HomeScreen() {
return <ListView style={{ flex: 1 }} />
}

然后在 Xcode 中启动项目，同时启动 metro dev server。

通过 Xcode View Hierarchy 看到，NativeView 已经正常渲染。

此文由 Mix Space 同步更新至 xLog
原始链接为 https://innei.in/posts/tech/use-native-components-in-expo