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

编辑富文本

编辑页面

了解在 React Native 中预览和编辑富文本的当前方法。


许多应用都需要让用户输入文本。例如,如果你想构建一款即时通讯或社交媒体应用,很可能会大量使用文本输入。React Native 开箱即带有 <TextInput> 组件,在许多简单场景中都能轻松满足需求。

不过,有时你需要更多灵活性。想想较长的社交媒体帖子、笔记应用或文档编辑器。理想情况下,你会希望支持不同的文本样式、列表、标题、内嵌图片等。这类功能称为富文本编辑器,而要在任何平台上做好它都很困难,React Native 也不例外。

目前,React Native 生态系统中还没有这类功能的默认解决方案。本指南将介绍现有方案及其取舍。对于大多数应用,可以从 Software Mansion 的原生编辑器入手:需要输出 markdown 时使用 react-native-enriched-markdown,需要输出 HTML 时使用 react-native-enriched-html。

观看:如何使用 DOM 组件构建富文本编辑器
观看:如何使用 DOM 组件构建富文本编辑器

使用 Expo DOM 组件在原生应用中渲染基于 Web 的编辑器,从而在 React Native 中实现富文本编辑器。

渲染富文本

显示富文本有很多不错的选择:

  • 对于 markdown 内容,你可以使用 markdown 渲染器,例如 react-native-enriched-markdown。

  • 对于 HTML 内容,你可以使用 @expo/html-elements 或 WebView(react-native-webview)。

  • 如果想要自定义格式并获得更多控制权,你可以利用嵌套的 <Text> 组件来渲染样式和布局。

    <TextInput> <Text> <Text style={{ fontWeight: 900 }}>Some bold text</Text>Some regular text </Text> </TextInput>
  • 你也可以使用 Expo Modules API 结合第三方库,例如 Android 上的 Markwon 和 iOS 上的 AttributedString,编写一个使用原生平台基础组件的自定义渲染组件。

编辑富文本的方法

要让富文本渲染正常工作,有几种不同的方法。不过,它们都有各自的限制。

原生编辑器

原生编辑器使用平台的文本 API 来渲染和编辑文本,而不是使用 WebView。它能提供原生性能和与应用其他部分一致的文本行为。Software Mansion 维护着两个采用这种方式的库:

react-native-live-markdown 是另一个原生方案。它可以直接替换 <TextInput>,并在每次按键时实时应用 markdown 格式。

你也可以使用 Expo Modules API 封装任何原生富文本编辑器,但如果在不同平台上使用不同的编辑器,就需要统一它们的 API 和输入格式。

目前也有一项工作,旨在将 lexical 编辑器移植到 Android 和 iOS,并提供 React Native 封装。要了解其进展,请参阅关于 React Native 支持的 lexical 讨论。

基于 WebView 的编辑器

大多数 React Native UI 组件封装的是原生平台基础组件,因此速度快、性能好,并且因此带有原生体验。而基于 WebView 的富文本编辑器采用的是不同的方法。

它们会把一个原本为 Web 构建的现有富文本编辑器,通过 JavaScript 包装在 react-native-webview 中。它可以在所有平台上运行(Android、iOS、Web),并且能利用 Web 平台上已有的流行富文本编辑器,但会带来性能和用户体验上的损耗。

你将无法在编辑器内部使用原生 UI 组件。诸如提及功能或图片嵌入之类特性的任何实现,都会重复造轮子,并且需要投入大量精力来实现。

现有的基于 WebView 的 React Native 库

如果要使用现成的基于 WebView 的编辑器,请使用 @10play/tentap-editor。如果你只需要一个配置有限的基础富文本编辑器,且对性能或用户体验没有严格要求,那么它很适合你。

自定义基于 WebView 的编辑器

如果你需要更强的可配置性,可以基于现有的仅 Web 编辑器构建一个类似的库。不过,你需要自己处理消息传递和 Web 端实现。这会让你获得底层编辑器提供的所有能力,并允许你实现更多功能。

你需要使用消息传递来在 WebView 与外部之间传递文本和 onChange 事件。由于富文本通常会变得很长,最好将其建模为非受控组件,以避免每次按键时都产生卡顿。另外,如果你能避免在每次按键时序列化并发送整个状态,也能提升性能。

基于 React Native TextInput 构建

在这一部分,我们来讨论是否有可能为通用场景提供一个功能完整的富文本输入框。

React Native 允许嵌套 <Text> 组件,并且允许它们作为 <TextInput> 的子元素来渲染和编辑样式化文本。它与新的 React Native 架构是同步的(onChange 事件会在文本输入字段中输入新字符后立即触发)。

不幸的是,<TextInput> 组件是围绕普通文本设计的,它在 onTextChange 回调中只返回一个字符串。这是一个很大的限制。

下面是一个快速示例。先渲染一个包含如下粗体文本的文本输入:

<TextInput> <Text> {/* 以下内容将以这种格式渲染粗体文本:**aa**aa */} <Text style={{ fontWeight: 900 }}>aa</Text>aa </Text> </TextInput>

然后,向文本输入中追加第五个字母 a。光标的位置应决定这个新字母是否属于粗体字符串的一部分。不幸的是,回调只会返回 aaaaa。

还有一个额外的 onSelectionChange 属性可以用来获取这类信息。不过,这会让任务变得更加困难。插入额外字符(例如用于列表或项目符号的换行)也会使选区不同步。

已经有一些尝试构建这种编辑器的项目,例如 markdown-editor(未积极维护)和 rn-text-editor(测试版),但目前没有广泛使用的包。

带可见样式标记的 Markdown 编辑器

如果使用 markdown 来设置文本样式就能满足你的需求,那么你可以在编辑时于单独的不可编辑视图中渲染 markdown。使用任何 markdown 渲染器自行构建都不复杂。

这种编辑体验适合高级用户或编程/技术类应用。你也可以探索在选中的文本块中渲染富文本,同时只显示 markdown,或者其他混合方案。

总结

虽然显示富文本有很多选择,但 React Native 中的富文本编辑并没有适用于所有场景的解决方案。对于大多数应用,可以从 Software Mansion 的原生编辑器入手。

当你需要 Web 编辑器独有的功能时,可以选择基于 WebView 的编辑器。只有在需求很简单时,才基于 React Native 基础组件构建,因为你必须自行处理选区和格式设置。