这篇文章讨论 Entity 系统。Draft 使用它来标记文本的类型。Entities 允许开发者将更加丰富的富文本内容添加到编辑器中。链接、提及和嵌入式的内容都可以使用 Entity 来实现。

在 Draft 的代码库中,link editorentity demo 提供了代码示例,来帮助理解 entities 的使用,和它们内建的行为。

Entity API Reference 提供了一些使用静态方法来创建,修改和更新 entity 对象的细节。
更多关于最近 Entity API 修改的信息和怎样更新你的应用的例子,可以看我们的 v0.10版本迁移指南

介绍

一个 Entity 对象代表 Draft 编辑器一行文本的元数据。它有3个属性:

  • type: 指示了 entity 的类型,例如:’LINK’、’MENTION’、’PHOTO’等。
  • mutability: 可变性。不要将不可变性和 immutable-js 混淆,此属性表示在编辑器中编辑文本范围时,使用此 Entity对象注释的一系列文本的行为。 这在下面更详细地讨论。
  • data: 一个包含了一些对于当前enity可选数据的对象。例如,’LINK’ enity包含了该链接的href值的数据对象。

所有的 entity 都存储在 ContentState 的记录中。这些 entity 被 ContentState 和组件中的 key 引用,用来装饰特定的行。(我们不建议使用以前的 api 来访问 entity,相关内容请参阅 issue #839)。

新建和获取 entity

可以使用 contentState.createEntity 来创建 entity,这个函数接收上边介绍的3个属性为参数。返回一个记录了刚新建的 entity 的 ContentState 对象。之后你就能够通过 contentState.getLastCreateEntityKey 来获取新建的 entity 的 key 了。

你可以通过这个 key 来将 entity 应用到你的内容中。例如 Modifier 模块包含了一个 applyEntity 方法:

  1. const contentState = editorState.getCurrentContent();
  2. const contentStateWithEntity = contentState.createEntity('LINK', 'MUTABLE', {
  3. url: 'http://www.zombo.com',
  4. });
  5. const entityKey = contentStateWithEntity.getLastCreatedEntityKey();
  6. const contentStateWithLink = Modifier.applyEntity(
  7. contentStateWithEntity,
  8. selectionState,
  9. entityKey,
  10. );
  11. const newEditorState = EditorState.push(editorState, {
  12. currentContent: contentStateWithLink,
  13. });

对于给定的文本,你能够在一个 ContentBlock 对象上,通过 getEntityAt 方法来获取 entity key 从而传递目标的 offset 值。

const contentState = editorState.getCurrentContent();
const blockWithLinkAtBeginning = contentState.getBlockForKey('...');
const linkKey = blockWithLinkAtBeginning.getEntityAt(0);
const linkInstance = contentState.getEntity(linkKey);
const {url} = linkInstance.getData();

“Mutability”

Entity的Mutability值有三种,分别代表了用户编辑对应内容时的三种表现状态。

请注意,DraftEntityInstance对象始终是不可变记录,此属性仅用于指示注释文本在编辑器中如何“突变”。(未来的变化可能会重命名此属性,以防止命名的潜在混淆。)

Immutable

如果不移除文本上的 entity,文本不能被改变。

例如在 Facebook 的文本框中,使用提及某个页面,当在提及中添加字符的时候,entity 会被移除,当删除字符的时候整个 entity 连同上边携带的文字也会被删除。

一般用在文字必须严格匹配上边所携带的元数据的情况。

Mutable

如果设置 MutabilityMutable,被加了 entity 的文字可以随意编辑。比如超链接的文字是可以随意编辑的,一般超链接的文字和链接的指向是没有关系的。

Segmented

设置为「segmented」的 entity 和设置为「Immutable」很类似,但是你可以自定义删除行为。

例如,在 Facebook 输入中,添加一个朋友的提及。 然后,添加一个字符到文本。 请注意,entity 从整个字符串中移除,因为您不能在提及的时候为你的朋友改名。

之后试着在一个提及中删除一个字符,你会发先删除的只是光标所在的块。并没有完全把当前的 entity 完全删除掉。这样我们就能够使用短名称来提及朋友了。

这里 可以直观体会三种 entity 的区别。

修改 Entities

DraftEntityInstance 记录是不可改变的,所以你不能直接修改 entity 中的 data 属性。

但 draft.js 提供了两个 entity 对象的方法来修改数据:mergeDatareplaceData。前者允许传入对象来合并数据,后者在更新数时完全替换。

在富文本内容中使用 Entities

本节中的下一篇文章会介绍使用 decorator 对象,可以用来找到 entity 并进行渲染。

链接编辑器提供了一个 entity 的创建和使用的示例。